Django配置django-cors-headers后仍出现CORS跨域错误如何解决
问题原因排查&解决方案
核心问题原因
- 中间件顺序错误:
django-cors-headers要求CorsMiddleware必须放在settings.py的MIDDLEWARE列表最顶部,优先级高于所有其他中间件,尤其要在django.middleware.common.CommonMiddleware之前。如果顺序不对,中间件只会给OPTIONS预检请求加CORS头,后续的实际GET/POST请求不会携带对应头,就会出现预检通过但实际请求被拦截的情况。 - 通配符Origin和带凭证请求冲突:你当前OPTIONS响应返回的是
Access-Control-Allow-Origin: *,如果你的实际请求携带了Cookie、Authorization头这类身份凭证,浏览器会直接拦截该请求。按照CORS规范,带身份凭证的请求不允许Origin使用通配符,必须返回和请求Origin完全匹配的域名,同时响应头还要携带Access-Control-Allow-Credentials: true。 - 配置逻辑冲突+版本适配问题:你同时开启了
CORS_ALLOW_ALL_ORIGINS=True和白名单配置,此时白名单会被自动忽略。此外3.x版本的django-cors-headers已经将CORS_ORIGIN_WHITELIST重命名为CORS_ALLOWED_ORIGINS,旧配置名虽有兼容但不推荐使用,且你当前的请求源http://10.0.123.123:8999不在你配置的白名单内,后续关闭全允许时会直接拦截。 - 视图逻辑绕过中间件:如果你的API视图是手动返回
HttpResponse/JsonResponse,或者做了自定义的响应头处理,有可能绕过CorsMiddleware的头部注入逻辑,导致实际响应没有CORS相关头。
修复步骤
- 首先调整
MIDDLEWARE顺序,确保CorsMiddleware放在第一位:
MIDDLEWARE = [ # 必须放在最顶部,优先所有其他中间件 'corsheaders.middleware.CorsMiddleware', 'django.middleware.common.CommonMiddleware', # 其余原有中间件保持不变 ]
- 如果你的请求需要携带身份凭证:
- 关闭全允许配置:
CORS_ALLOW_ALL_ORIGINS = False - 替换旧白名单配置,添加实际请求源:
CORS_ALLOWED_ORIGINS = [ 'http://localhost:3000', 'http://10.0.123.123:8999' ]
- 新增凭证允许配置:
CORS_ALLOW_CREDENTIALS = True
- 如果不需要携带身份凭证,直接检查实际GET/POST请求的响应头是否存在
Access-Control-Allow-Origin,如果不存在排查Nginx层是否覆盖了响应头,或者视图逻辑是否清空了响应头。
内容的提问来源于stack exchange,提问作者Guddu
相关产品推荐
相关产品推荐

