Nginx反向代理Django时CORS预请求报错求助
解决CORS策略错误:请求头access-control-allow-origin不被允许
问题情况
使用Nginx部署React静态文件,Waitress运行Django REST Framework(API服务地址0.0.0.0:8000),Nginx作为Django的反向代理。已开启Django的全源允许,Nginx配置中添加了跨域请求头和预请求头,但仍收到以下错误:
“Access to XMLHttpRequest at 'http://15.295.156.60:8000/core/profile/profile/' from origin 'http://15.295.156.60' has been blocked by CORS policy: Request header field access-control-allow-origin is not allowed by Access-Control-Allow-Headers in preflight response.”
已尝试操作:
- 修改Nginx配置,为反向代理添加跨域和预请求头
- 修改Django设置,允许所有源
当前配置
Django配置
CORS_ALLOW_ALL_ORIGINS = True CORS_ORIGIN_WHITELIST = [ 'http://192.168.56.1:80', 'http://localhost:3000', 'http://*', # Add any other origins that you want to allow here ]
前端Axios请求代码
const axiosInstance = axios.create({ baseURL: baseURL, timeout: 5000, headers: { Authorization: localStorage.getItem('access_token') ? 'JWT ' + localStorage.getItem('access_token') : null, 'Content-Type': 'application/json', accept: 'application/json', }, });
Nginx反向代理配置
location / { root "C:/Users/Administrator/Desktop/build"; try_files $uri $uri/ /index.html; } location /core/ { # Handle preflight requests (OPTIONS) if ($request_method = 'OPTIONS') { add_header 'Access-Control-Allow-Origin' * always; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always; add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type' always; add_header 'Access-Control-Allow-Credentials' 'true' always; add_header 'Content-Length' 0; add_header 'Content-Type' 'text/plain charset=UTF-8'; return 204; } add_header 'Access-Control-Allow-Origin' * always; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always; add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type' always; add_header 'Access-Control-Allow-Credentials' 'true' always; proxy_pass http://15.295.156.60:8000; }
问题根源与修复方案
1. 错误核心原因
- 报错提示
access-control-allow-origin不被允许,说明预请求响应的Access-Control-Allow-Headers未覆盖前端实际发送的请求头(比如你的前端里有accept头,但Nginx配置里没加)。 CORS_ORIGIN_WHITELIST中的http://*是无效配置,Django不支持通配符,且已开启CORS_ALLOW_ALL_ORIGINS = True,这个白名单完全多余。- Nginx同时设置
Access-Control-Allow-Origin: *和Access-Control-Allow-Credentials: true是冲突的——带凭证的跨域请求不允许用通配符作为允许源。
2. 分步修复
步骤1:清理Django CORS配置
保留核心配置即可,删除无效的白名单:
CORS_ALLOW_ALL_ORIGINS = True # 若需要带Cookie等凭证,保留下面一行;不需要则删除 # CORS_ALLOW_CREDENTIALS = True
步骤2:修正Nginx跨域配置
- 把通配符
*替换为具体的前端源http://15.295.156.60(如果需要凭证),或者删除Access-Control-Allow-Credentials(不需要凭证时)。 - 在
Access-Control-Allow-Headers中添加前端实际发送的accept头,确保覆盖所有请求头。 - 添加代理头传递真实请求信息给Django。
修改后的Nginx配置示例:
location / { root "C:/Users/Administrator/Desktop/build"; try_files $uri $uri/ /index.html; } location /core/ { # 处理预请求 if ($request_method = 'OPTIONS') { add_header 'Access-Control-Allow-Origin' 'http://15.295.156.60' always; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always; # 包含所有前端发送的请求头 add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type, accept' always; # 带凭证时保留,否则删除 add_header 'Access-Control-Allow-Credentials' 'true' always; add_header 'Content-Length' 0; add_header 'Content-Type' 'text/plain charset=UTF-8'; return 204; } add_header 'Access-Control-Allow-Origin' 'http://15.295.156.60' always; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always; add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type, accept' always; add_header 'Access-Control-Allow-Credentials' 'true' always; proxy_pass http://15.295.156.60:8000; # 传递真实请求信息给Django proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; }
步骤3:检查前端请求
确认前端没有错误将access-control-allow-origin作为请求头发送(你的Axios代码目前没有这个问题,可检查全局拦截器是否有额外添加)。
步骤4:重启服务
- 重启Django服务
- 重启Nginx服务,确保配置生效
内容的提问来源于stack exchange,提问作者Parameshwar Kumawath
相关产品推荐
相关产品推荐

