Nginx 反向代理配置 API 鉴权后出现 CORS 跨域报错,主要原因是浏览器的 OPTIONS 预检请求被 Nginx 鉴权模块拦截或未返回必要的 CORS 响应头。解决核心是在 Nginx 配置中显式放行 OPTIONS 请求,使其跳过鉴权直接返回 204 状态码及 CORS 头。
先说结论:必须在 Nginx 配置中单独处理 OPTIONS 请求,确保其不触发鉴权逻辑且携带正确的跨域响应头。
- 先确认:使用 curl 检查 OPTIONS 请求是否返回 401 或 403 状态码。
- 先处理:在 location 块中添加 if 判断或独立 location 放行 OPTIONS 方法。
- 再验证:浏览器开发者工具 Network 面板显示 OPTIONS 请求状态为 200 或 204。
命令速用版
location /api/ {
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
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,Authorization';
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain; charset=utf-8';
add_header 'Content-Length' 0;
return 204;
}
# 原有鉴权配置
auth_request /auth;
proxy_pass http://backend;
}为什么会这样
浏览器在发送跨域 POST 或 PUT 请求前,会自动发送 OPTIONS 预检请求询问服务器是否允许。Nginx 开启鉴权后,默认会对所有请求包括 OPTIONS 进行认证检查。如果鉴权失败或鉴权模块未正确传递 CORS 头,浏览器会拦截后续请求。
分步处理
1. 打开 Nginx 配置文件,定位到对应的 server 或 location 块。
2. 在鉴权指令之前插入 OPTIONS 请求判断逻辑,确保 return 204 提前执行。
3. 检查 add_header 指令是否被后续配置覆盖,必要时在多个块中重复声明。
4. 执行 nginx -t 检查配置语法,执行 nginx -s reload 重载配置。
怎么验证是否生效
在客户端机器执行 curl -v -X OPTIONS https://your-domain.com/api/test,观察响应头是否包含 Access-Control-Allow-Origin 且状态码为 204 或 200。浏览器 F12 Network 面板中 OPTIONS 请求不应显示红色报错。
常见坑
1. add_header 继承问题:Nginx 中 add_header 在子块中不会自动继承父块,需在每个 location 中单独配置。
2. 鉴权子请求影响:使用 auth_request 模块时,子请求可能消耗掉 CORS 头,需在 auth_request 对应的 location 中也放行 OPTIONS。
3. 通配符风险:Access-Control-Allow-Origin 设置为 * 无法携带 Cookie,涉及凭证时需动态匹配域名。
常见问题
为什么配置了 add_header 还是没有 CORS 头?
通常是因为 Nginx 返回了错误状态码(如 401/403/500),默认配置下 add_header 对这些状态码不生效。需要添加 always 参数,例如 add_header 'Access-Control-Allow-Origin' '*' always;。
OPTIONS 请求需要走鉴权吗?
不需要。OPTIONS 是预检请求,不应携带凭证,走鉴权会导致跨域失败。必须在 Nginx 层直接放行。
为什么本地测试正常,生产环境报错?
检查生产环境是否有 CDN 或前置负载均衡拦截了 OPTIONS 请求,或者 SSL 证书配置导致握手阶段失败。