actix-web全局CORS限制不生效,如何仅允许指定域名访问?
问题原因
直接从localhost发起的请求属于同源请求,浏览器不会发送Origin请求头。actix-cors的规则仅对携带Origin头的跨域请求生效——没有Origin头的请求,中间件不会触发拦截逻辑,自然能正常获取资源。
block_on_origin_mismatch(true)的作用是:当请求带有Origin头但不在允许列表中时,直接返回错误响应,而非返回不带CORS头的内容。但它对无Origin头的请求不起作用。
实现仅允许指定域名访问的方案
方案1:标准CORS配置(针对跨域场景)
这是符合CORS规范的用法,允许同源请求,仅拦截非法跨域请求。确保配置完整后,通过跨域场景测试:
.wrap( Cors::default() .allowed_origin("https://google.com") // 按需添加允许的HTTP方法 .allowed_methods(vec!["GET", "POST", "PUT", "DELETE"]) // 按需添加允许的请求头 .allowed_headers(HeaderName::from_str("Content-Type").unwrap()) .block_on_origin_mismatch(true), )
测试方式:打开https://google.com,在浏览器控制台执行fetch('http://localhost:8080/your-api'),此时请求会携带Origin: https://google.com头,能正常访问;从其他域名(比如https://baidu.com)发起同样请求则会被拦截返回错误。
方案2:拦截所有非指定来源的请求(含同源请求)
如果需要连同源请求也拦截,仅允许带有指定Origin头的请求,需添加自定义中间件配合CORS:
use actix_web::{dev::ServiceRequest, dev::ServiceResponse, Error, middleware::Next}; async fn enforce_origin(req: ServiceRequest, next: Next) -> Result<ServiceResponse, Error> { // 检查Origin头 match req.headers().get("Origin") { Some(origin) if origin == "https://google.com" => { // 符合要求,继续处理请求 next.call(req).await } _ => { // 不符合,返回403错误 Ok(req.into_response( actix_web::HttpResponse::Forbidden() .body("Origin not allowed") .into_body(), )) } } } // 在main中注册中间件(放在CORS中间件之前) App::new() .wrap_fn(enforce_origin) .wrap( Cors::default() .allowed_origin("https://google.com") .block_on_origin_mismatch(true), ) // 注册API端点 .route("/your-api", web::get().to(your_api_handler))
这种方式下,无论是否跨域,只有带有Origin: https://google.com头的请求才能正常访问,其他请求(包括直接访问localhost的同源请求)都会被拒绝。
内容的提问来源于stack exchange,提问作者Matthew Trent
相关产品推荐
相关产品推荐

