ensure_csrf_cookie装饰器无法在浏览器Cookie中设置CSRF令牌问题
问题分析
核心问题是跨域请求时浏览器未保存CSRF Cookie:直接访问URL有效是因为同域请求不受跨域限制,而前端通过fetch发起跨域请求时,必须同时满足前后端的跨域凭证配置,才能让Cookie正常设置。
解决方案
1. 修正Django配置(settings.py)
修改以下关键配置项:
# 开启跨域凭证支持(必须设为True才能跨域携带/设置Cookie) CORS_ALLOW_CREDENTIALS = True # 关闭全局跨域允许,避免和白名单规则冲突 CORS_ORIGIN_ALLOW_ALL = False # 明确信任的前端域名(和前端实际访问地址保持一致) CORS_ORIGIN_WHITELIST = [ 'http://localhost:3000', 'http://127.0.0.1:3000' ] # 更新CSRF信任源,包含前端完整地址 CSRF_TRUSTED_ORIGINS = [ 'http://localhost:3000', 'http://127.0.0.1:3000' ]
注意:CORS_ORIGIN_ALLOW_ALL=True与CORS_ORIGIN_WHITELIST不能同时生效,保留白名单更符合生产环境的安全要求。
2. 修改React的fetch请求配置
在fetchCsrfToken函数中添加credentials: 'include'参数,允许浏览器在跨域请求中携带和设置Cookie:
async function fetchCsrfToken() { try { const res = await fetch(`http://127.0.0.1:8000/accounts/csrf_cookie`, { method: "GET", credentials: 'include', // 新增此行 headers: { Accept: "application/json", "Content-Type": "application/json", }, }); if (!res.ok) { console.log("Problem"); } else { const context = await res.json(); console.log(context); // 请求完成后再获取Cookie,确保拿到最新值 setcsrftoken(getCookie("csrftoken")); } } catch (e) { // showMessage("Error: Unexpected error has occurred!", "Error"); } }
3. 调整React组件的useEffect逻辑
原代码中fetchCsrfToken是异步操作,直接在useEffect中调用setcsrftoken会因请求未完成而拿不到Cookie,需调整为等待请求完成后再更新状态:
const CSRFToken = () => { const [csrftoken, setcsrftoken] = useState(""); useEffect(() => { console.log("useEffect"); // 用async/await确保请求完成后再获取Cookie const getToken = async () => { await fetchCsrfToken(); setcsrftoken(getCookie("csrftoken")); }; getToken(); }, []); return ( <> <input className="csrfmiddlewaretoken" type="hidden" name="csrfmiddlewaretoken" value={csrftoken} /> </> ); };
验证步骤
- 重启Django后端服务
- 重新启动React前端
- 打开浏览器开发者工具的Application > Cookies面板,发起请求后检查是否存在
csrftokenCookie - 后续POST请求时,需在请求头中携带
X-CSRFToken字段,值为获取到的csrftoken
内容的提问来源于stack exchange,提问作者GermanProgrammer99
相关产品推荐
相关产品推荐

