Nginx 跨域问题的解决方案

crawley by crawley · 2025 年 4 月 25 日

一、跨域问题本质

浏览器基于 同源策略 (Same-Origin Policy) 限制以下行为:

  • 触发条件:协议、域名、端口任一不同
  • 限制类型:AJAX 请求、 Web 字体、 Web Workers 等
  • 异常提示No 'Access-Control-Allow-Origin' header is present

二、 Nginx 核心解决方案

方案 1:CORS 响应头配置

原理:通过设置 HTTP 响应头告知浏览器允许跨域

server {
    location / {
        <em># 基础跨域配置</em>
        add_header 'Access-Control-Allow-Origin' '*' always;
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
        add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,Content-Type,Authorization' always;
        add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range' always;

        <em># 预检请求缓存</em>
        add_header 'Access-Control-Max-Age' 1728000 always;

        <em># 处理 OPTIONS 预检请求</em>
        if ($request_method = 'OPTIONS') {
            return 204;
        }
    }
}

方案 2:反向代理

原理:将跨域请求转换为同源请求

server {
    listen 80;
    server_name api.yourdomain.com;

    location / {
        proxy_pass http://backend-server:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        <em># 可选:添加CORS头双重保障</em>
        add_header 'Access-Control-Allow-Origin' 'https://your-frontend.com';
    }
}

三、高级配置技巧

1. 动态允许来源

map $http_origin $cors_header {
    default "";
    ~^https?://(.*\.)?yourdomain.com(:\d+)?$ $http_origin;
    ~^https?://localhost(:\d+)?$ $http_origin;
}

server {
    add_header 'Access-Control-Allow-Origin' $cors_header always;
}

2. 带凭证的请求

add_header 'Access-Control-Allow-Credentials' 'true' always;
<em># 必须指定具体域名,不能使用 *</em>
add_header 'Access-Control-Allow-Origin' 'https://your-frontend.com' always;

3. WebSocket 跨域

location /websocket/ {
    proxy_pass http://backend_ws;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "Upgrade";
    proxy_set_header Host $host;

    <em># CORS for WebSocket</em>
    if ($http_origin ~* (https?://.*\.yourdomain.com$)) {
        add_header 'Access-Control-Allow-Origin' $http_origin;
        add_header 'Access-Control-Allow-Credentials' 'true';
    }
}

四、最佳实践建议

  1. 安全策略
    • 生产环境避免使用 * 通配符使用 HTTPS 强制加密传输
    add_header 'Access-Control-Allow-Origin' 'https://trusted-domain.com'; add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
  2. 性能优化
    • 合理设置 Access-Control-Max-Age 减少预检请求合并静态资源请求
    location ~* \.(woff2?|ttf|eot|svg|png|jpg)$ { add_header 'Access-Control-Allow-Origin' 'https://cdn.yourdomain.com'; expires 365d; }
  3. 调试技巧
    • 使用 curl 验证响应头
    curl -I -X OPTIONS https://api.yourdomain.com/resource
    • Chrome DevTools 网络标签检查 Headers

五、常见问题排查

问题现象可能原因解决方案
配置生效但浏览器仍报错缓存未更新强制刷新 (Ctrl+F5) 或禁用缓存调试
OPTIONS 请求返回 404Nginx 未正确处理 OPTIONS 方法添加 if ($request_method = 'OPTIONS')  处理块
部分请求头未通过未在 Access-Control-Allow-Headers  列出添加缺失的请求头如 Authorization
带 Cookie 请求失败未设置 Allow-Credentials配置 add_header 'Access-Control-Allow-Credentials' 'true'

通过以上配置策略,可构建安全高效的跨域解决方案。建议根据实际业务需求选择组合方案,并通过压力测试验证配置效果。

0 0 投票数
文章评分