Nginx跨域需在server或location块中用add_header配置CORS头,并显式处理OPTIONS预检请求;核心头包括Access-Control-Allow-Origin(生产环境禁用*)、Allow-Methods、Allow-Headers、Allow-Credentials;预检必须return 204且重复设置所有头;允许多域名可用map指令动态匹配。

直接在 server 或 location 块里加 add_header 指令,配合预检请求(OPTIONS)处理逻辑,就能生效。关键不是“结构多复杂”,而是响应头是否在最终返回给浏览器的 HTTP 响应中正确出现。
必须配置的核心响应头
这些头决定了浏览器是否放行跨域响应:
-
Access-Control-Allow-Origin:指定允许访问的源。开发环境可临时用
'*',生产环境必须写具体域名(如'https://example.com'),否则带凭证(cookie)的请求会失败 -
Access-Control-Allow-Methods:列出允许的 HTTP 方法,如
'GET, POST, PUT, DELETE, OPTIONS'。注意要包含OPTIONS,否则预检会失败 -
Access-Control-Allow-Headers:声明前端实际会发送的请求头,比如
'Content-Type, Authorization, X-Requested-With'。漏掉任意一个,预检就过不了 -
Access-Control-Allow-Credentials:若前端设置了
withCredentials: true(例如传 cookie),此项必须为'true',且Allow-Origin不能是'*'
必须处理 OPTIONS 预检请求
浏览器对非简单请求(如 Content-Type: application/json、带 Authorization 头)会先发一次 OPTIONS 请求。Nginx 必须拦截并快速响应,不能把它转发给后端:
- 用
if ($request_method = 'OPTIONS') { ... return 204; }显式捕获 - 在
if块内重复设置所有 CORS 头(包括Allow-Origin),因为add_header在if外定义的不会继承到if内部 - 返回
204 No Content最稳妥,避免后端误处理或日志干扰
推荐的完整 location 配置片段
这是经过多个项目验证的最小可行模板,放在 location / 或具体 API 路径下即可:
location /api/ {
# 处理预检请求
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' 'https://example.com';
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';
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain; charset=utf-8';
add_header 'Content-Length' 0;
return 204;
}
<pre class="brush:php;toolbar:false;"># 正常请求响应头
add_header 'Access-Control-Allow-Origin' 'https://example.com';
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';
add_header 'Access-Control-Expose-Headers' 'X-Total-Count, X-Request-ID';
proxy_pass http://backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;}
允许多个域名的动态方案
Nginx 不支持数组式配置,但可用 map 指令实现白名单匹配:
- 在
http块顶部定义映射关系:
map $http_origin $cors_origin {
default "";
"~^https?://(localhost|example\.com|app\.mycompany\.com)(:[0-9]+)?$" $http_origin;
}
- 在
location中使用变量:add_header 'Access-Control-Allow-Origin' $cors_origin; - 这样既安全又灵活,避免硬编码或滥用
*











