React对接Django REST Framework无法自动存储CSRF Token与Session ID
核心错误1:SameSite与Secure属性配置违反浏览器强制规则
现代Chrome(80及以上版本)、Firefox对Cookie属性有强制校验:当SameSite属性设置为None时,必须同时开启Secure属性(即仅允许HTTPS环境传输),否则浏览器会直接拒绝存储该Cookie,不会执行Set-Cookie指令。
你当前配置中同时设置了:
SESSION_COOKIE_SAMESITE = 'None' CSRF_COOKIE_SAMESITE = 'None' CSRF_COOKIE_SECURE = False SESSION_COOKIE_SECURE = False
这是Cookie无法存入的最核心原因,本地开发阶段二选一修复即可:
- 方案一(本地HTTP环境推荐):直接将两个Cookie的SameSite属性改为Django默认值
Lax,无需开启Secure,完全满足本地跨端口调试需求:
SESSION_COOKIE_SAMESITE = 'Lax' CSRF_COOKIE_SAMESITE = 'Lax'
- 方案二:如果确实需要跨站传递Cookie,本地搭建HTTPS调试环境,同时将两个SECURE配置改为
True。
核心错误2:前端错误配置CORS相关请求头
Access-Control-Allow-Origin、Access-Control-Allow-Credentials属于服务端返回的响应头,不应该出现在前端请求头中。你手动在axios请求头中添加这两个字段,会触发CORS预检请求失败,直接导致浏览器拦截响应中的Set-Cookie指令。
直接删除请求配置中这两个无效头,保留必要配置即可:
const config = { headers: { 'content-type': 'application/json', 'X-CSRFToken': Cookies.get('csrftoken') }, withCredentials: true }
另外你当前useEffect中手动获取CSRF Token、手动写入Cookie的逻辑完全多余:@ensure_csrf_cookie装饰器的作用就是在访问对应接口时,自动通过响应头Set-Cookie下发csrftoken,浏览器会自动完成存储,不需要从响应体取值再手动写入。而且你当前代码取响应字段response['data']['csrf']和后端返回的success字段根本不匹配,手动写入逻辑本身也无法正常运行,直接删掉这段冗余代码即可。
注意:前端所有接口请求必须统一域名,要么全用http://127.0.0.1:8000要么全用http://localhost:8000,二者属于不同源,Cookie不互通,混用会导致Cookie存储后无法正常携带。
核心错误3:跨域中间件顺序错误
corsheaders的中间件必须放在DjangoCommonMiddleware之前,否则CORS相关响应头不会正常返回,会导致浏览器拦截跨域响应。确认settings.py中中间件顺序如下:
MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'corsheaders.middleware.CorsMiddleware', # 必须放在CommonMiddleware之前 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ]
另外你给登录接口加了csrf_exempt豁免属于不必要的安全风险,等Cookie存储、CSRF头携带正常后,直接移除该装饰器即可,Django会自动完成CSRF校验。
验证方法
改完所有配置后重启Django服务,清空浏览器对应站点的所有缓存和Cookie再测试:
- 打开开发者工具Network面板,访问
/csrf/接口,查看响应头的Set-Cookie字段,csrftoken条目无浏览器拦截的黄色警告标识 - 提交登录请求,登录成功后响应头会通过Set-Cookie下发sessionid,打开Application面板的Cookies存储项,能看到csrftoken、sessionid均已自动存入对应域名下
- 后续所有请求开启
withCredentials: true后,浏览器会自动携带对应Cookie,不需要额外手动处理。
内容的提问来源于stack exchange,提问作者Lothric

