必须同时设置 SESSION_COOKIE_SAMESITE 和 CSRF_COOKIE_SAMESITE 为 'None',且两者均需配对 SECURE=True,否则浏览器底层拦截 Cookie;根本原因是 Django 默认 SESSION_COOKIE_SAMESITE='Lax' 导致跨域不携带 sessionid,CSRF_COOKIE_SAMESITE 非 'None' 则 csrftoken 不下发,配合 CORS_ALLOW_CREDENTIALS=True、中间件顺序正确及前端 withCredentials=true 才能生效。

必须同时设置 SESSION_COOKIE_SAMESITE 和 CSRF_COOKIE_SAMESITE 为 'None',且两者都得配对 SECURE=True,否则浏览器直接拒绝写入或发送 Cookie——这不是前端没发、也不是后端没设,是浏览器在底层就拦截了。
为什么登录后 request.user 总是 AnonymousUser
根本原因是 Django 默认的 SESSION_COOKIE_SAMESITE = 'Lax',跨域请求下浏览器不携带 sessionid Cookie。即使响应头里有 Set-Cookie,DevTools 的 Application → Cookies 标签页也看不到它,Network 面板里 Request Headers 更不会出现 Cookie 字段。
-
SESSION_COOKIE_SAMESITE必须显式设为字符串'None'(不是 Python 的None) -
SESSION_COOKIE_SECURE必须为True(生产环境强制 HTTPS;开发环境用 HTTP 时可临时设False,但此时SAMESITE得回退到'Lax') -
SESSION_COOKIE_HTTPONLY = False(仅当你需要前端 JS 读取 sessionid 时才开,比如登出逻辑) -
SESSION_COOKIE_PATH = '/'(确保覆盖所有 API 路径)
为什么 Axios 请求始终报 CSRF cookie not set
Django 的 CsrfViewMiddleware 自动管理 csrftoken Cookie,它不认你视图里手动调用的 response.set_cookie(..., samesite='None')。真正起作用的是全局配置 CSRF_COOKIE_SAMESITE。
-
CSRF_COOKIE_SAMESITE = 'None'是硬性要求,缺它就永远收不到csrftoken -
CSRF_COOKIE_SECURE = True必须同步开启——SameSite=None在非 HTTPS 下会被现代浏览器静默丢弃 -
CSRF_COOKIE_HTTPONLY = False(因为前端需通过document.cookie或getCookie()提取 token,塞进X-CSRFToken请求头) - 搭配
@ensure_csrf_cookie装饰器用于首次获取 token 的接口(如/api/user/),否则可能首次请求就失败
CORS 配置里最容易漏掉的三个点
django-cors-headers 不是装上就完事,中间件顺序和凭证配置错一个,Cookie 就全废。
立即学习“Python免费学习笔记(深入)”;
-
CORS_ALLOW_CREDENTIALS = True必须设,且不能和通配符CORS_ALLOW_ALL_ORIGINS = True共存(浏览器会直接拒收 Cookie) -
CORS_ALLOWED_ORIGINS必须写全协议+域名+端口(如['https://your-react-app.com', 'http://localhost:3000']),CORS_ORIGIN_WHITELIST已弃用 -
CorsMiddleware必须放在SessionMiddleware和CsrfViewMiddleware之前——顺序错了,中间件根本拿不到 Cookie
前端 Axios 必须加 withCredentials 且清缓存验证
光后端配对没用,前端不主动声明“我要带 Cookie”,浏览器连发都不发。
-
axios.defaults.withCredentials = true(全局设)或单个请求加{ withCredentials: true } - 发 POST/PUT/DELETE 前,必须从
document.cookie或响应头里拿到csrftoken,并作为X-CSRFToken头发出 - 改完配置后必须硬重载:Ctrl+Shift+R(Win/Linux)或 Cmd+Shift+R(macOS),否则旧 Cookie 和缓存策略还在生效
- 验证是否生效:看 Network → 任一请求的 Response Headers 是否含
Set-Cookie: csrftoken=...和Set-Cookie: sessionid=...,再看下一请求的 Request Headers 是否有Cookie字段
最常被忽略的是 CSRF_TRUSTED_ORIGINS(Django 4.0+ 必填),它和 CORS_ALLOWED_ORIGINS 不是一回事:前者用于校验 Referer,后者控制 Access-Control-Allow-Origin,漏掉它会导致 CSRF 校验直接 403。


















