React前端+Django后端跨域问题:Access-Control-Allow-Origin多值错误
解决React+Django架构的CORS跨域错误
错误核心原因
浏览器提示Access-Control-Allow-Origin头包含多个值,说明至少有两个来源在返回这个头——要么是你以为关闭的Django仍在输出CORS头,要么是Nginx配置里重复添加了该头,同时请求跳转(3xx)导致两次返回头叠加。
分步解决步骤
1. 彻底确认Django的CORS功能已关闭
- 卸载
django-cors-headers包(如果之前安装过):pip uninstall django-cors-headers - 检查Django的
settings.py,确保以下内容被移除或注释:# INSTALLED_APPS 里的 'corsheaders' # MIDDLEWARE 里的 'corsheaders.middleware.CorsMiddleware' # 所有以CORS_开头的配置项(比如CORS_ALLOW_ALL_ORIGINS等) - 重启Django后端服务。
2. 修复Nginx的API服务配置(关键)
你的api.sitename.com配置存在两个严重问题:
- 核心请求路径
/未代理到Django后端(proxy_pass被注释),导致/documents请求无法正确路由到后端,触发不必要的跳转。 - 用
if指令添加CORS头(Nginx的if存在逻辑陷阱,容易导致重复添加)。
修改后的api.sitename.com的server块如下:
server { server_name api.sitename.com; listen 80; server_tokens off; client_max_body_size 10m; root /var/html/; # 统一处理所有API请求,代理到Django后端 location / { proxy_set_header Host $host; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Server $host; proxy_set_header X-Forwarded-For $remote_addr; proxy_pass http://backend:8000; # 统一配置CORS头,避免重复 # 若前端不需要带Cookie,可替换为 '*' add_header Access-Control-Allow-Origin "http://www.sitename.com" always; add_header Access-Control-Allow-Methods "GET, POST, OPTIONS, HEAD" always; add_header Access-Control-Allow-Headers "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization" always; add_header Access-Control-Expose-Headers "Content-Length,Content-Range" always; # 直接响应OPTIONS预检请求 if ($request_method = OPTIONS) { return 204; } } # 保留原有的静态资源和admin配置 location /media/ { autoindex on; } location /docs/ { root /usr/share/nginx/html; try_files $uri $uri/redoc.html; } location /static/rest_framework/ { autoindex on; } location /static/admin/ { autoindex on; } # 原/admin/代理可保留,或合并到上面的/代理中 location /admin/ { proxy_set_header Host $host; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Server $host; proxy_pass http://backend:8000/admin/; } }
3. 验证配置并重启服务
- 检查Nginx配置语法:
nginx -t - 重启Nginx生效:
systemctl restart nginx - 用curl测试CORS头是否唯一:
查看返回头中curl -I -H "Origin: http://www.sitename.com" http://api.sitename.com/documents/15/Access-Control-Allow-Origin是否只有一个值(要么是指定的域名,要么是*)。
4. 处理跳转问题
如果仍出现跳转提示,检查:
- Django的
settings.py中APPEND_SLASH是否为True(默认是),确保请求路径末尾带斜杠。 - Nginx的
proxy_pass末尾是否带斜杠:若后端路由不带前缀,用proxy_pass http://backend:8000;(不带斜杠),避免路径拼接错误。
内容的提问来源于stack exchange,提问作者Саша Асеев
相关产品推荐
相关产品推荐

