什么是“过于宽松的CORS策略”

26 阅读2分钟

CORS(Cross-Origin Resource Sharing,跨域资源共享)是一种浏览器安全机制,用于控制不同源(协议、域名、端口任一不同即为不同源)的网页能否请求和获取当前服务器的资源,本质是通过服务器返回的 HTTP 响应头来实现权限管控,保护服务器资源不被恶意跨域请求滥用。

过于宽松的 CORS 策略:核心风险

过于宽松的 CORS 配置会完全失去跨域访问的安全防护作用,其中最危险的两种配置及风险如下:

1. 允许所有来源:Access-Control-Allow-Origin: *

这是最常见的宽松配置,服务器通过该响应头表示 “接受任意域名的跨域请求”。

2. 允许所有 HTTP 方法 / 请求头 / 暴露敏感响应头

  • Access-Control-Allow-Methods: *:允许任意 HTTP 方法(GET、POST、PUT、DELETE、OPTIONS 等),恶意攻击者可跨域执行删除、修改等破坏性操作;
  • Access-Control-Allow-Headers: *:允许客户端携带任意自定义请求头,可能绕过部分基于请求头的身份验证逻辑;
  • Access-Control-Expose-Headers: *:暴露服务器所有响应头给客户端,可能泄露 Token、用户 ID、服务器配置等敏感信息;

如何识别过于宽松的 CORS 配置?

找到跨域请求对应的接口(可通过「Fetch/XHR」筛选),点击该请求,查看以下字段是否为宽松配置:

  • Access-Control-Allow-Origin 是否为 *
  • Access-Control-Allow-Methods 是否为 *
  • Access-Control-Allow-Headers 是否为 *
  • 若存在以上任一情况,即为过于宽松的 CORS 配置。

修复方案

1. 核心修复:指定具体的允许来源(禁用 *

// Java 示例
String origin = request.getHeader("Origin");
// 白名单配置
List<String> allowedOrigins = Arrays.asList("https://a.com", "https://b.com");
if (allowedOrigins.contains(origin)) {
    response.setHeader("Access-Control-Allow-Origin", origin);
}

2. 限制允许的 HTTP 方法

Access-Control-Allow-Methods: GET, POST, PUT

3. 明确允许的请求头

Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-With

4. 可选优化:限制凭证访问与缓存

  • 若需要跨域携带 Cookie / 凭证,配置:Access-Control-Allow-Credentials: true(注意:此时Access-Control-Allow-Origin不能是*,必须是具体域名);
  • 配置 CORS 响应缓存,减少预检请求开销:Access-Control-Max-Age: 86400(缓存 1 天);
  • 按需暴露响应头,避免泄露敏感信息:Access-Control-Expose-Headers: Content-Length, X-Total-Count(只暴露必要字段)

常见场景-Nginx 配置(生产环境常用)

server {
    listen 443 ssl;
    server_name your-server.com;

    # 跨域配置
    add_header Access-Control-Allow-Origin https://your-legitimate.com always;
    add_header Access-Control-Allow-Methods GET,POST,PUT always;
    add_header Access-Control-Allow-Headers Content-Type,Authorization always;
    add_header Access-Control-Allow-Credentials true always;
    add_header Access-Control-Max-Age 86400 always;

    # 处理预检请求(OPTIONS请求直接返回204)
    if ($request_method = OPTIONS) {
        return 204;
    }

    # 其他配置...
}