React向Django后端发起登录POST请求时遇CORS及CSRF验证问题
解决React向Django LoginView发起POST请求的CORS/CSRF问题
核心问题分析
LoginView依赖Django的CSRF验证机制,即使配置了CORS和代理,若前端未正确获取/发送CSRF令牌,或后端Cookie配置不当,就会触发验证失败。
后端(Django)配置调整
- 清理重复配置
新版django-cors-headers使用CORS_ALLOWED_ORIGINS,旧版的CORS_ORIGINS_WHITELIST可以删除,避免配置冲突。 - 确认中间件顺序
确保CorsMiddleware在CommonMiddleware之前,settings.py的MIDDLEWARE数组需按此顺序排列:MIDDLEWARE = [ 'corsheaders.middleware.CorsMiddleware', 'django.middleware.common.CommonMiddleware', # 其他中间件... 'django.middleware.csrf.CsrfViewMiddleware', # 其他中间件... ] - Cookie相关配置
本地开发环境下,调整以下Cookie配置适配跨域场景:CSRF_COOKIE_SECURE = False # 非HTTPS环境下禁用 CSRF_COOKIE_HTTPONLY = False # 允许前端JS读取令牌(手动提取时需要) CSRF_COOKIE_SAMESITE = 'Lax' # 适配现代浏览器Cookie规则 SESSION_COOKIE_SECURE = False SESSION_COOKIE_SAMESITE = 'Lax'
前端(React)请求配置
- 使用代理路径发起请求
因为已配置React代理,直接用相对路径发起请求,不要写全量后端URL:// 正确写法 fetch('/accounts/login/', { /* 请求配置 */ }) // 错误写法 fetch('http://localhost:8000/accounts/login/', { /* 请求配置 */ }) - 确保请求携带Credentials
无论是fetch还是axios,都要开启凭证携带,让浏览器自动发送CSRF Cookie:- fetch示例:
// 提取CSRF令牌的工具函数 function getCsrfToken() { let token = null; const cookies = document.cookie.split(';'); for (const cookie of cookies) { const [key, value] = cookie.trim().split('='); if (key === 'csrftoken') { token = decodeURIComponent(value); break; } } return token; } // 登录请求逻辑 async function login(username, password) { const csrfToken = getCsrfToken(); const response = await fetch('/accounts/login/', { method: 'POST', credentials: 'include', // 关键:携带Cookie headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'X-CSRFToken': csrfToken }, body: new URLSearchParams({ username: username, password: password }) }); return response; } - axios示例:
// 全局配置开启凭证携带 axios.defaults.withCredentials = true; async function login(username, password) { const csrfToken = getCsrfToken(); // 复用上面的工具函数 const response = await axios.post('/accounts/login/', new URLSearchParams({ username, password }), { headers: { 'X-CSRFToken': csrfToken, 'Content-Type': 'application/x-www-form-urlencoded' } } ); return response; }
- fetch示例:
- 预获取CSRF Cookie
如果页面加载后未自动获取到csrftokenCookie,可在页面初始化时发起一个GET请求触发后端设置Cookie:// 页面初始化时执行 async function initCsrf() { await fetch('/accounts/login/', { method: 'GET', credentials: 'include' }); }
排查验证步骤
- 打开浏览器控制台,进入Application > Cookies > http://localhost:3000,确认存在
csrftokenCookie。 - 查看登录POST请求的Request Headers,确认:
- 包含
Cookie: csrftoken=xxx - 包含
X-CSRFToken: xxx
- 包含
- 检查请求的Content-Type是否为
application/x-www-form-urlencoded,LoginView默认不处理JSON格式的请求体。
内容的提问来源于stack exchange,提问作者Sufian Shaikh
相关产品推荐
相关产品推荐

