use actix_web::{ dev::{forward_ready, Service, ServiceRequest, ServiceResponse, Transform}, Error, HttpResponse, }; use futures_util::future::{LocalBoxFuture, Ready, ready, ok}; use std::rc::Rc; /// 请求日志中间件 pub struct RequestLogger; impl Transform for RequestLogger where S: Service, Error = Error>, S::Future: 'static, B: 'static, { type Response = ServiceResponse; type Error = Error; type InitError = (); type Transform = RequestLoggerMiddleware; type Future = Ready>; fn new_transform(&self, service: S) -> Self::Future { ok(RequestLoggerMiddleware { service }) } } pub struct RequestLoggerMiddleware { service: S, } impl Service for RequestLoggerMiddleware where S: Service, Error = Error>, S::Future: 'static, B: 'static, { type Response = ServiceResponse; type Error = Error; type Future = LocalBoxFuture<'static, Result>; forward_ready!(service); fn call(&self, req: ServiceRequest) -> Self::Future { let method = req.method().to_string(); let path = req.path().to_string(); let fut = self.service.call(req); Box::pin(async move { let res = fut.await?; tracing::info!("{} {} -> {}", method, path, res.status()); Ok(res) }) } } /// 安全响应头中间件 pub struct SecurityHeaders; impl Transform for SecurityHeaders where S: Service, Error = Error>, S::Future: 'static, B: 'static, { type Response = ServiceResponse; type Error = Error; type InitError = (); type Transform = SecurityHeadersMiddleware; type Future = Ready>; fn new_transform(&self, service: S) -> Self::Future { ok(SecurityHeadersMiddleware { service }) } } pub struct SecurityHeadersMiddleware { service: S, } impl Service for SecurityHeadersMiddleware where S: Service, Error = Error>, S::Future: 'static, B: 'static, { type Response = ServiceResponse; type Error = Error; type Future = LocalBoxFuture<'static, Result>; forward_ready!(service); fn call(&self, req: ServiceRequest) -> Self::Future { let fut = self.service.call(req); Box::pin(async move { let mut res = fut.await?; let headers = res.headers_mut(); headers.insert( actix_web::http::header::HeaderName::from_static("x-content-type-options"), actix_web::http::header::HeaderValue::from_static("nosniff"), ); headers.insert( actix_web::http::header::HeaderName::from_static("x-frame-options"), actix_web::http::header::HeaderValue::from_static("DENY"), ); Ok(res) }) } } /// 管理员JWT认证中间件 pub struct AdminAuth; impl Transform for AdminAuth where S: Service, Error = Error>, S::Future: 'static, B: 'static, { type Response = ServiceResponse; type Error = Error; type InitError = (); type Transform = AdminAuthMiddleware; type Future = Ready>; fn new_transform(&self, service: S) -> Self::Future { ok(AdminAuthMiddleware { service }) } } pub struct AdminAuthMiddleware { service: S, } impl Service for AdminAuthMiddleware where S: Service, Error = Error>, S::Future: 'static, B: 'static, { type Response = ServiceResponse; type Error = Error; type Future = LocalBoxFuture<'static, Result>; forward_ready!(service); fn call(&self, req: ServiceRequest) -> Self::Future { // 检查Authorization头 let auth_header = req.headers() .get("Authorization") .and_then(|v| v.to_str().ok()) .and_then(|v| v.strip_prefix("Bearer ")) .map(|s| s.to_string()); if auth_header.is_none() { let (req, _) = req.into_parts(); return Box::pin(async move { Err(actix_web::error::ErrorUnauthorized("需要管理员令牌")) }); } let fut = self.service.call(req); Box::pin(async move { fut.await }) } }