React+DRF单页应用登出时CSRF Token验证失败问题求助
解决DRF+React会话认证下登出CSRF验证失败问题
问题根源分析
你遇到的错误核心是请求头中的CSRF Token与Django会话中存储的Token不匹配,主要可能由以下几个原因导致:
- 前端通过接口获取Token的方式存在问题,拿到的Token与当前会话的实际Token不一致
- 跨域配置未正确允许携带凭证,导致会话Cookie未被传递
CSRF_COOKIE_HTTPONLY配置错误,导致Token读取或匹配逻辑混乱
具体解决方案
方案1:直接从浏览器Cookie读取Token(推荐)
Django默认CSRF_COOKIE_HTTPONLY = False,csrftoken Cookie前端可直接读取,无需额外接口获取,这是最可靠的方式:
前端代码修改
// 新增提取Cookie的工具函数 function getCsrfToken() { let token = null; if (document.cookie) { const cookies = document.cookie.split(';').map(c => c.trim()); for (const cookie of cookies) { if (cookie.startsWith('csrftoken=')) { token = decodeURIComponent(cookie.split('=')[1]); break; } } } return token; } // 登出请求逻辑 const csrfToken = getCsrfToken(); fetch(`${APIURL}/api/logout/`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRFToken': csrfToken, }, credentials: 'include', // 必须携带会话Cookie }) .then(res => { // 处理登出成功逻辑 }) .catch(err => console.error('登出失败:', err));
后端调整
可以直接删除csrf_token视图,因为Django会在用户首次访问受CSRF保护的视图(比如登录接口)时自动设置csrftoken Cookie。
方案2:保留HTTP Only Cookie的场景(仅当必须开启CSRF_COOKIE_HTTPONLY = True时)
如果你的项目因安全需求必须设置CSRF_COOKIE_HTTPONLY = True,则需要确保:
- 调用
/api/csrf-token/接口时必须携带会话Cookie,这样get_token(request)返回的才是当前会话对应的Token - 前端请求该接口时也要加上
credentials: "include"
修改前端获取Token的逻辑
fetch(`${APIURL}/api/csrf-token/`, { credentials: 'include' }) .then(res => res.json()) .then(data => { const csrfToken = data['X-CSRFToken']; return fetch(`${APIURL}/api/logout/`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRFToken': csrfToken, }, credentials: 'include', }); }) .then(res => { // 处理登出逻辑 });
后端配置检查
确保settings.py中:
CSRF_COOKIE_HTTPONLY = True CORS_ALLOW_CREDENTIALS = True CORS_ALLOWED_ORIGINS = ['你的前端域名'] # 比如"http://localhost:3000" SESSION_COOKIE_SAMESITE = 'Lax' # 跨域场景可设为'None'(需配合HTTPS) SESSION_COOKIE_SECURE = True # HTTPS环境下开启
关于HTTP Only csrftoken Cookie的疑问
- 如果设置了
CSRF_COOKIE_HTTPONLY = True,前端无法读取该Cookie,此时必须通过后端接口获取Token,且请求接口时要携带会话Cookie,才能拿到对应会话的Token - 不建议开启
CSRF_COOKIE_HTTPONLY,因为CSRF Token本身需要被前端读取并发送给后端验证,开启HTTP Only会增加复杂度,除非有特殊安全要求
内容的提问来源于stack exchange,提问作者kureal
相关产品推荐
相关产品推荐

