本文详解 django + react 跨域场景下 csrf cookie(csrftoken)无法发送与接收的根本原因及完整配置方案,涵盖前后端关键设置、samesite 属性适配、cors 配置验证及调试要点。
本文详解 django + react 跨域场景下 csrf cookie(csrftoken)无法发送与接收的根本原因及完整配置方案,涵盖前后端关键设置、samesite 属性适配、cors 配置验证及调试要点。
在 Django 与 React 前后端分离架构中,当 React 应用部署于独立域名(如 CodeSandbox 的 https://7w37f9-3000.csb.app),而 Django 后端运行于 https://eliptum.tech 时,跨域请求需同时满足「凭证传递」与「CSRF 防护」双重约束。常见错误提示 CSRF cookie not set 并非后端未生成 token,而是浏览器因安全策略拒绝存储或发送该 Cookie —— 核心症结在于 Django 默认的 CSRF_COOKIE_SAMESITE = 'Lax' 与跨域 samesite='None' 要求冲突。
✅ 必须补充的关键 Django 设置
仅在视图中调用 response.set_cookie(..., samesite='None') 是不够的。Django 的全局 CSRF Cookie 行为由以下两个设置共同控制,缺一不可:
# settings.py CSRF_COOKIE_SECURE = True # 强制仅通过 HTTPS 传输(生产环境必需) CSRF_COOKIE_SAMESITE = 'None' # 允许跨站上下文发送 cookie(关键!)
⚠️ 注意:CSRF_COOKIE_SAMESITE = 'None' 必须与 CSRF_COOKIE_SECURE = True 成对启用,否则现代浏览器(Chrome/Firefox)将直接拒绝设置该 Cookie。
? 完整 CORS 与会话配置校验清单
确保 settings.py 中以下配置已正确声明(你已部分配置,但需确认完整性):
# 必需的跨域基础配置
CORS_ALLOW_CREDENTIALS = True
CORS_ALLOWED_ORIGINS = [
'https://eliptum.tech',
'https://7w37f9-3000.csb.app', # 显式写全,避免变量引用隐患
]
# CSRF 信任源(Django 4.0+ 推荐使用,替代旧版 CSRF_TRUSTED_ORIGINS)
CSRF_TRUSTED_ORIGINS = [
'https://eliptum.tech',
'https://7w37f9-3000.csb.app',
]
# 会话 Cookie 同样需兼容跨域(若依赖 session_id)
SESSION_COOKIE_SECURE = True
SESSION_COOKIE_SAMESITE = 'None'
# 确保 corsheaders 中间件位置正确(应在 SessionMiddleware 和 CsrfViewMiddleware 之后)
MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware', # 必须在 SecurityMiddleware 之后、SessionMiddleware 之前
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware', # 注意:CsrfViewMiddleware 不能被跳过
# ... 其他中间件
]? 前端 Axios 请求规范(无额外修改)
你当前的 Axios 配置已正确,无需调整:
// 获取公钥 & CSRF Token(首次请求触发 Cookie 设置)
const res = await axios.get('https://eliptum.tech/get-public-key', {
withCredentials: true, // ✅ 关键:启用凭证
});
// 后续 POST 请求自动携带 csrftoken cookie + 手动传 X-CSRFToken 头
await axios.post('https://eliptum.tech/user/create', { /* data */ }, {
withCredentials: true,
headers: {
'X-CSRFToken': res.data.csrf_token, // ✅ 服务端返回的 token 值
}
});? 原理说明:Django 的 CsrfViewMiddleware 会检查两个来源——1) X-CSRFToken 请求头(优先);2) csrftoken Cookie(备用)。因此即使 Cookie 因配置问题未生效,只要手动传入 X-CSRFToken,请求仍可通过。但 Cookie 未设成功会导致后续无头请求失败,且违背设计意图。
? 常见陷阱与调试建议
浏览器开发者工具验证:
在 Network 面板中查看 get-public-key 响应头,确认存在:
Set-Cookie: csrftoken=xxx; expires=...; HttpOnly; Path=/; SameSite=None; Secure
若缺失 SameSite=None; Secure,则 CSRF_COOKIE_SAMESITE 或 CSRF_COOKIE_SECURE 未生效。避免混合协议:确保前端和后端全程使用 HTTPS。http:// 源无法接收 Secure Cookie。
Django 版本注意:
CSRF_COOKIE_SAMESITE = 'None' 在 Django ≥ 3.1 中完全支持;若使用旧版本,请升级或改用 django-csp 等方案。本地开发绕过?不推荐:
开发时若用 http://localhost:3000,需将 CSRF_COOKIE_SAMESITE 改为 'Lax' 或 'Strict',并移除 CSRF_COOKIE_SECURE —— 但上线前务必切回 'None' + Secure。
✅ 总结:三步闭环修复
| 步骤 | 操作 | 验证方式 |
|---|---|---|
| 1. 后端 Cookie 策略 | CSRF_COOKIE_SAMESITE = 'None' + CSRF_COOKIE_SECURE = True | 检查响应头 Set-Cookie 是否含 SameSite=None; Secure |
| 2. 前端凭证透传 | 所有 axios 请求保持 withCredentials: true | 查看请求头是否含 Cookie: csrftoken=...(POST 时) |
| 3. CSRF Token 双保险 | 视图返回 csrf_token 字段 + 请求头 X-CSRFToken 显式传递 | 后端日志或断点确认 request.META.get('HTTP_X_CSRFTOKEN') 存在 |
完成上述配置后,跨域请求将稳定携带 CSRF Cookie,CSRF cookie not set 错误彻底消失,React 与 Django 的安全通信即可可靠建立。

















