Nginx配置CORS需用always确保所有响应(含错误和OPTIONS)携带头;credentials为true时Origin须动态白名单匹配,禁用*;必须显式拦截OPTIONS并return 204;CORS配置应限定在API的location块内,避免污染静态资源。

在 Nginx 中配置跨域资源共享(CORS)头,关键不是简单加几行 add_header,而是让响应头精准、稳定、安全地生效——尤其要覆盖 OPTIONS 预检请求、适配凭证(credentials)逻辑、避免被后端或缓存覆盖。
必须用 always 参数确保所有响应都带 CORS 头
Nginx 默认只在 2xx/3xx 成功响应中注入 add_header,但错误响应(如 401、500)或预检返回的 204 响应不会自动携带。浏览器遇到无 CORS 头的 OPTIONS 响应,直接报 “CORS header ‘Access-Control-Allow-Origin’ missing”。
正确写法是每条头都加 always:
add_header 'Access-Control-Allow-Origin' 'https://your-app.com' always;add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization, X-Requested-With' always;add_header 'Access-Control-Expose-Headers' 'X-Total-Count, X-Request-ID' always;
严格区分是否启用 credentials
如果前端请求设置了 credentials: true(比如带 Cookie 或 Authorization),则 Access-Control-Allow-Origin 不能为 *,否则浏览器强制拒绝。此时必须动态匹配合法源。
推荐用 map 指令构建白名单:
map $http_origin $cors_origin { default ""; "~^https?://(www\.)?myapp\.com(:[0-9]+)?$" $http_origin; "~^https://staging\.myapp\.com$" $http_origin; }- 再在 location 中引用:
add_header 'Access-Control-Allow-Origin' $cors_origin always; - 同时开启凭证支持:
add_header 'Access-Control-Allow-Credentials' 'true' always;
单独拦截并快速响应 OPTIONS 预检请求
浏览器对非简单请求(如带自定义 header、PUT/DELETE 方法)会先发 OPTIONS 请求。Nginx 若不拦截,就会把请求转发给后端——而多数后端不处理 OPTIONS,导致 404 或 502,跨域失败。
必须在同一 location 块内显式处理:
if ($request_method = 'OPTIONS') {add_header 'Access-Control-Allow-Origin' $cors_origin always;add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization, X-Requested-With' always;add_header 'Access-Control-Max-Age' 1728000 always;add_header 'Content-Length' 0 always;return 204;}
注意:if 是独立作用域,里面要用的 CORS 头必须重复写,不能继承外层。
把 CORS 配置放在正确的 location 块里
不要写在 server 或根 location / 下,否则静态资源、健康检查接口、favicon 等都会被污染。
按用途精准定位:
- API 接口:
location /api/ { proxy_pass http://backend; … } - 静态资源(JS/CSS/字体):
location ~* \.(js|css|woff2|ttf|png)$ { … } - 避免
if + proxy_pass混用——这会导致 502、header 丢失、Host 头缺失等隐蔽问题。


















