React+Django DRF中无法获取响应头CSRF Token和SessionID的问题
核心原因
浏览器出于安全限制,禁止JavaScript直接读取响应头中的Set-Cookie字段——哪怕你将SESSION_COOKIE_HTTPONLY和CSRF_COOKIE_HTTPONLY设为false也不行。这是同源策略的内置规则:开发者工具能看到Set-Cookie是给调试用的,但不允许前端JS代码直接访问,和你的配置无关。
正确处理方式
1. 无需手动获取SessionID和CSRF Token
你已经设置了axios.defaults.withCredentials = true,这会让浏览器自动管理Cookie:登录请求成功后,浏览器会自动把sessionid和csrftoken存入本地Cookie,后续所有符合CORS规则的Axios请求,都会自动带上这些Cookie,后端的SessionAuthentication会自动识别认证状态,完全不需要你手动读取或携带。
验证方法:登录后发起一个需要认证的请求(比如获取当前用户信息),打开浏览器Network面板查看该请求的Request Headers,如果看到Cookie字段包含sessionid=xxx; csrftoken=xxx,说明认证已经生效。
2. 特殊场景下手动获取CSRF Token
如果业务确实需要拿到CSRF Token(比如用原生fetch发起请求、或在其他场景复用),不要从Set-Cookie头取,而是让后端在响应体或自定义响应头中额外返回CSRF值:
- 后端视图示例:
from rest_framework.response import Response from rest_framework.decorators import api_view @api_view(['POST']) def login_view(request): # 执行登录逻辑... csrf_token = request.META.get('CSRF_COOKIE') return Response({ 'success': True, 'csrf_token': csrf_token })
- 前端直接读取
response.data.csrf_token即可。
配置优化建议
调整以下Django配置,避免潜在的Cookie存储问题:
- 将
CSRF_COOKIE_SAMESITE和SESSION_COOKIE_SAMESITE从'None'改为'Lax':本地开发用HTTP协议时,None要求Cookie必须是Secure(即HTTPS环境),否则浏览器可能拒绝存储Cookie
CSRF_COOKIE_SAMESITE = 'Lax' SESSION_COOKIE_SAMESITE = 'Lax'
- 统一域名:当前前端请求的后端地址是
http://127.0.0.1:8000,但CSRF_TRUSTED_ORIGINS配置的是http://localhost:5173,127.0.0.1和localhost属于不同域名,建议统一为同一域名(比如都用localhost或都用127.0.0.1)
验证步骤
- 登录请求成功后,打开浏览器Application面板 → Cookies → 查看
http://127.0.0.1:8000下是否存在sessionid和csrftokenCookie。 - 发起一个需要认证的GET请求(比如
/api/user/),查看请求头是否携带Cookie字段。 - 如果后端返回用户信息,说明Session认证已正常工作。
内容的提问来源于stack exchange,提问作者mushi
相关产品推荐
相关产品推荐

