加 cors 头仍 403 或预检失败,主因是中间件顺序错误(corsmiddleware 必须在 commonmiddleware 之前)、cors_allow_headers 未包含 authorization 等非简单头、生产环境误用 cors_allow_all_origins、nginx 未透传 cors 响应头或缓存/缓冲区配置不当。

为什么加了 corsheaders 还是 403 或预检失败?
常见现象是:前端发 POST 或带自定义 header 的请求时,浏览器先发 OPTIONS 预检,Django 返回 403 —— 这往往不是没装中间件,而是中间件顺序或配置漏项。
关键点:corsheaders 必须在 django.middleware.common.CommonMiddleware 之前,否则 OPTIONS 请求会被后者拦截并返回空响应(无 CORS 头),导致预检失败。
- 检查
MIDDLEWARE列表,确保'corsheaders.middleware.CorsMiddleware'在'django.middleware.common.CommonMiddleware'上方 - 确认
INSTALLED_APPS中已注册'corsheaders' -
CORS_ALLOW_ALL_ORIGINS = True仅适用于开发;生产环境必须用CORS_ALLOWED_ORIGINS显式声明(如['http://localhost:3000', 'https://myapp.com']) - 如果前端带 cookie,需同时设
CORS_ALLOW_CREDENTIALS = True,且CORS_ALLOWED_ORIGINS不能为['*'](浏览器强制拒绝)
如何让 Django 放行带 Authorization 或 Content-Type: application/json 的请求?
默认情况下,corsheaders 不自动放行非简单 header(如 Authorization)或非简单 Content-Type(如 application/json),会触发预检,但若未显式允许,预检响应中缺失 Access-Control-Allow-Headers,前端报错“Request header field Authorization is not allowed by Access-Control-Allow-Headers”。
- 添加
CORS_ALLOW_HEADERS = ['*'](开发可接受)或精确列出:['content-type', 'authorization', 'x-csrftoken'] - 若用 JWT,在前端请求头写
Authorization: Bearer xxx,后端必须把authorization加入CORS_ALLOW_HEADERS -
CORS_EXPOSE_HEADERS仅控制哪些响应头能被前端 JS 读取(如X-Total-Count),和跨域放行无关,别混淆
Django REST Framework + corsheaders 组合下,CSRF 和 CORS 怎么共存?
前后端分离时,前端通常不走 Django 模板,CSRF 保护默认失效;但若仍需 CSRF(比如部分接口要求 session 登录),就会和 CORS 冲突:浏览器因缺少 SameSite 或 credentials 配置拒绝发送 cookie,导致 CSRF 验证失败。
- 前端 axios/fetch 发请求时必须设
withCredentials: true(或credentials: 'include') - Django 端需配
CORS_ALLOW_CREDENTIALS = True,且CORS_ALLOWED_ORIGINS不能含通配符 - 确保
SESSION_COOKIE_SAMESITE = 'Lax'(或'None'+SESSION_COOKIE_SECURE = True,仅限 HTTPS) - DRF 的
SessionAuthentication依赖 cookie,若只用 TokenAuthentication,则无需处理 CSRF,CORS_ALLOW_CREDENTIALS可设为False
生产环境部署 Nginx 后,CORS 头突然消失?
常见于 Nginx 反向代理 Django 时,Nginx 默认不透传响应头,尤其 Access-Control-Allow-Origin 这类自定义头会被过滤掉,浏览器收不到,仍报跨域。
- Nginx 配置里加
add_header 'Access-Control-Allow-Origin' '$http_origin' always;(注意always,否则 4xx/5xx 响应不生效) - 同时透传其他 CORS 头:
add_header 'Access-Control-Allow-Credentials' 'true' always;、add_header 'Access-Control-Allow-Headers' '$http_access_control_request_headers' always; - 更稳妥的做法是:关掉 Nginx 的 CORS 头,确保所有 CORS 逻辑由 Django
corsheaders控制,Nginx 只做代理,不干预响应头
真正容易被忽略的是预检缓存时间(Access-Control-Max-Age)和 header 大小限制——Nginx 默认 large_client_header_buffers 较小,遇到长 origin 或多 header 的 OPTIONS 请求可能直接 400。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











