Nginx 配置 CORS 跨域访问控制的核心是使用 add_header 指令在响应中注入 Access-Control 系列头信息,并在 location 块中单独处理 OPTIONS 预检请求。该方案适用于 Nginx 作为反向代理或静态资源服务器的场景,风险边界在于错误配置 Access-Control-Allow-Origin 为通配符且同时开启 Allow-Credentials 会导致浏览器拒绝请求。
先说结论:Nginx 通过 add_header 指令直接添加 CORS 响应头,必须显式放行 OPTIONS 方法以避免预检请求失败。
- 适合:Nginx 反向代理 API 接口或前端静态资源跨域访问场景
- 先准备:确认前端请求的 Origin 域名、HTTP 方法及自定义 Header 列表
- 验收:使用 curl 命令携带 Origin 头验证响应头是否完整返回
命令速用版
以下配置片段可直接放入 server 或 location 块中,注意根据实际域名修改 Access-Control-Allow-Origin 的值。
location / {
proxy_pass http://backend;
# 允许跨域源
add_header Access-Control-Allow-Origin "https://example.com";
# 允许跨域方法
add_header Access-Control-Allow-Methods "GET, POST, OPTIONS";
# 允许跨域头
add_header Access-Control-Allow-Headers "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range";
# 允许携带凭证
add_header Access-Control-Allow-Credentials "true";
# 处理预检请求
if ($request_method = 'OPTIONS') {
add_header Access-Control-Allow-Origin "https://example.com";
add_header Access-Control-Allow-Methods "GET, POST, OPTIONS";
add_header Access-Control-Allow-Headers "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range";
add_header Access-Control-Max-Age 1728000;
add_header Content-Type 'text/plain; charset=utf-8';
add_header Content-Length 0;
return 204;
}
}
为什么会这样
浏览器出于安全策略,默认禁止跨域 HTTP 请求,除非服务器响应中包含特定的 CORS 头信息。
Nginx 作为反向代理时,后端服务可能未配置 CORS 头,或者 Nginx 缓存了不带 CORS 头的响应。通过在 Nginx 层统一注入头信息,可以确保客户端无论请求哪个后端节点都能收到一致的跨域许可。OPTIONS 预检请求是浏览器在发送复杂请求前自动发起的探测,若 Nginx 未对该方法返回 200 状态码及对应头信息,正式请求会被浏览器拦截。
分步处理
1. 编辑 Nginx 配置文件,通常位于 /etc/nginx/nginx.conf 或 /etc/nginx/conf.d/ 目录下。
2. 在对应的 server 或 location 块中添加 add_header 指令,指定 Access-Control-Allow-Origin 为前端域名。
3. 增加 if 判断语句拦截 $request_method 为 OPTIONS 的请求,直接返回 204 状态码并携带 CORS 头。
4. 执行 nginx -t 检查配置语法,确认无误后执行 nginx -s reload 重载配置。
怎么验证是否生效
使用 curl 命令模拟带 Origin 头的请求,检查响应头中是否包含 Access-Control-Allow-Origin。
curl -v -H "Origin: https://example.com" -X OPTIONS https://your-nginx-domain.com
观察输出中是否有 < Access-Control-Allow-Origin: https://example.com 字段。同时在浏览器开发者工具的 Network 面板中,确认预检请求状态码为 200 或 204,且正式请求未报 CORS 错误。
常见坑
1. add_header 继承问题:在 if 块中使用 add_header 时,外部定义的 add_header 可能不会自动继承,需要在 if 块内重新定义所有需要的头。
2. 通配符与凭证冲突:Access-Control-Allow-Origin 设置为 * 时,Access-Control-Allow-Credentials 不能设置为 true,否则浏览器会报错。
3. 缓存干扰:若 Nginx 开启了 proxy_cache,可能缓存了不带 CORS 头的后端响应,需配置 proxy_ignore_headers 或在 Nginx 层强制覆盖头信息。
常见问题
Access-Control-Allow-Origin 可以设置为星号吗
可以设置为星号表示允许所有域名,但如果需要携带 Cookie 等凭证信息,则必须指定具体域名且不能为星号。
为什么 OPTIONS 请求返回 403 或 404
通常是因为 Nginx 配置中未显式放行 OPTIONS 方法,或者后端服务拦截了该请求,需在 Nginx 层直接返回 204 避免请求透传到后端。
配置生效后浏览器仍报 CORS 错误怎么办
检查响应头是否真的返回,确认是否有重定向导致头信息丢失,并清除浏览器缓存后重试。
参考来源
- MDN Web Docs: HTTP 访问控制 (CORS) - https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CORS
- Nginx Official Documentation: ngx_http_headers_module - https://nginx.org/en/docs/http/ngx_http_headers_module.html