✅nginx跨域必须用add_header加access-control-头,且需加always参数;必须写在实际处理请求的location块内;预检请求(options)须显式拦截返回204并带全cors头;带credentials时origin不能为。

在 Nginx 中用 add_header 配置跨域头,本质是让 Nginx 在响应中补上浏览器所需的 Access-Control-* 字段。关键不在“加不加”,而在“加对位置、加对值、加对时机”。
必须加 always 参数,否则多数情况失效
Nginx 默认只在某些状态码(如 200、204、304)响应中生效 add_header;而跨域预检请求(OPTIONS)返回的是 204,错误页可能是 404 或 502——这些场景下,不加 always 就不会发跨域头,导致前端报错。
- 正确写法:
add_header Access-Control-Allow-Origin "*" always; - 错误写法:
add_header Access-Control-Allow-Origin "*";(204/404 响应里没头) - 所有跨域相关头都建议统一加
always,包括Allow-Methods、Allow-Headers等
跨域头必须写在真正处理请求的 location 块里
add_header 不继承、不叠加,server 级配置不会自动落到子 location 中。比如你代理的是 /api/,但把跨域头只写在 server 块顶层,而 Nginx 实际用的是 location /api/ 块里的 proxy_pass,那 server 级的头就完全不起作用。
- 静态资源(如
location ~ \.(js|css|png)$)也要单独加跨域头,否则前端加载 JS 时可能因资源本身跨域被拦截 - 宝塔面板里,“添加响应头”功能默认只作用于
location /,若接口在/api/下,必须进「配置文件」手动编辑对应 location 块 - 反向代理场景下,确认后端没返回同名头,否则 Nginx 默认不覆盖(除非用
proxy_hide_header主动隐藏)
区分预检请求和正式请求,OPTIONS 必须显式处理
浏览器对非简单请求(如带 Authorization、Content-Type: application/json 或非 GET/POST 方法)会先发一次 OPTIONS 请求。Nginx 默认不处理它,必须拦截并返回 204 + 全套 CORS 头。
- 在对应
location内加:if ($request_method = 'OPTIONS') { add_header ... always; return 204; } - 不要在 if 块里做复杂逻辑(如 proxy_pass),仅用于快速响应预检
-
Access-Control-Max-Age可设为 86400(24 小时),减少重复预检
携带 Cookie 时,Origin 不能用通配符 *
如果前端设置了 credentials: true(比如要传 Cookie 或 Authorization),那么 Access-Control-Allow-Origin 必须写具体协议+域名,例如 https://example.com,绝不能是 *,否则浏览器直接拒绝响应。
- 同时需配
add_header Access-Control-Allow-Credentials "true" always; - 前端 fetch 要写全:
fetch(url, { credentials: 'include' }) - 多域名支持?可用变量动态匹配,例如:
add_header Access-Control-Allow-Origin $http_origin always;,再配合if判断白名单











