全部学科
NodeJS全栈
nodejs
Python全栈
python
小程序首页
📅 2026-05-20 7 分钟 ✍️ juanwangdev

跨域资源共享(CORS)安全配置

CORS 控制浏览器跨域请求的能力。NGINX 作为反向代理可统一添加 CORS 响应头,实现集中管理的跨域策略。

基础 CORS 配置

简单跨域

nginx
server {
    location /api/ {
        add_header 'Access-Control-Allow-Origin' 'https://app.example.com';
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization';
        add_header 'Access-Control-Allow-Credentials' 'true';
        
        if ($request_method = 'OPTIONS') {
            add_header 'Access-Control-Max-Age' 86400;
            add_header 'Content-Type' 'text/plain charset=UTF-8';
            add_header 'Content-Length' 0;
            return 204;
        }
        
        proxy_pass http://backend;
    }
}

Access-Control-Allow-Credentials: trueOrigin 不能使用 *,必须指定具体域名。

动态 Origin 白名单

多域名 CORS

nginx
map $http_origin $cors_origin {
    default "";
    "~^https://(www\.)?example\.com$" $http_origin;
    "~^https://app\.example\.com$" $http_origin;
    "~^https://admin\.example\.com$" $http_origin;
}

server {
    location /api/ {
        if ($cors_origin != "") {
            add_header 'Access-Control-Allow-Origin' $cors_origin;
        }
        add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization, X-Requested-With';
        add_header 'Access-Control-Allow-Credentials' 'true';
        
        if ($request_method = 'OPTIONS') {
            return 204;
        }
        
        proxy_pass http://backend;
    }
}

使用 map 指令根据请求的 Origin 动态匹配,只允许白名单中的域名。

安全注意事项

避免通配符

nginx
# 危险 - 不要这样做
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' '*';

通配符允许任何站点跨域访问,可能导致 CSRF 攻击和数据泄露。

Preflight 请求处理

nginx
location /api/ {
    # 预检请求直接返回,不转发到后端
    if ($request_method = 'OPTIONS') {
        add_header 'Access-Control-Allow-Origin' $cors_origin;
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization';
        add_header 'Access-Control-Max-Age' 3600;
        return 204;
    }
    
    # 正常请求转发到后端
    if ($cors_origin != "") {
        add_header 'Access-Control-Allow-Origin' $cors_origin;
        add_header 'Access-Control-Allow-Credentials' 'true';
    }
    
    proxy_pass http://backend;
}

OPTIONS 预检请求由 NGINX 直接处理,减少后端压力。Max-Age 控制浏览器缓存预检结果的时间。

子域名通配

匹配同域所有子域名

nginx
map $http_origin $cors_origin {
    default "";
    "~^https://[a-z0-9-]+\.example\.com$" $http_origin;
}

正则匹配任意字母数字和连字符组成的子域名,但不会匹配 example.com 本身。

不同路径不同策略

nginx
server {
    # 公开 API - 宽松策略
    location /api/public/ {
        add_header 'Access-Control-Allow-Origin' '*';
        add_header 'Access-Control-Allow-Methods' 'GET, OPTIONS';
        
        if ($request_method = 'OPTIONS') {
            return 204;
        }
        
        proxy_pass http://backend;
    }
    
    # 私有 API - 严格策略
    location /api/private/ {
        if ($cors_origin != "") {
            add_header 'Access-Control-Allow-Origin' $cors_origin;
            add_header 'Access-Control-Allow-Credentials' 'true';
        }
        
        proxy_pass http://backend;
    }
}

要点总结

  • 使用 map 指令实现动态 Origin 白名单,避免通配符
  • Credentials: trueOrigin 不能为 *
  • OPTIONS 预检请求由 NGINX 直接返回 204,减少后端压力
  • Max-Age 控制浏览器缓存预检结果,减少请求次数
  • 公开接口和私有接口使用不同 CORS 策略
  • 避免设置过于宽松的 Allow-Headers,仅暴露必要的头

📝 发现内容有误?点击此处直接编辑

← 上一篇 访问控制与IP白名单
下一篇 → 隐藏Nginx版本号
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库