已存在CSRF Token却提示缺失?Vue+DRF跨域请求问题排查
Vue + Axios 调用DRF接口CSRF错误排查与解决
一、Axios为啥突然不自动带X-CSRFToken了?
- Axios默认只认
XSRF-TOKEN这个Cookie名,而Django的CSRF Cookie叫csrftoken——之前能正常工作,大概率是你之前全局配置过xsrfCookieName和xsrfHeaderName,现在配置被覆盖或者没加载到 - 不是所有请求Axios都会自动带CSRF头:默认只对
PUT/POST/DELETE这类非GET请求触发,如果你改了请求方法或者Axios实例的配置,可能就失效了 - 域名同源问题:哪怕开发者工具能看到Cookie,只要前端和后端的域名(包括端口、协议)不是完全同源,或者子域名没配置共享Cookie,JS就读不到
csrftoken,自然带不了头
二、强制携带X-CSRFToken的几种方法
1. 全局配置Axios实例
直接在创建Axios实例时指定对应参数,和Django的设置对齐:
import axios from 'axios' const api = axios.create({ baseURL: '你的DRF接口地址', xsrfCookieName: 'csrftoken', // 对应Django默认的CSRF Cookie名 xsrfHeaderName: 'X-CSRFToken', // Django要求的请求头名 withCredentials: true // 必须开,不然Cookie带不出去 }) export default api
2. 加请求拦截器手动塞头
如果全局配置不管用,写个拦截器手动从Cookie里抠出Token:
// 先写个工具函数拿csrftoken function getCsrfToken() { const match = document.cookie.match(/csrftoken=([^;]+)/) return match ? match[1] : '' } // 给Axios加拦截器,非GET请求强制加头 axios.interceptors.request.use(config => { if (config.method.toLowerCase() !== 'get') { config.headers['X-CSRFToken'] = getCsrfToken() } return config })
3. 页面初始化时直接设默认头
简单粗暴,直接把Token塞进Axios的全局默认头:
const csrfToken = document.cookie.match(/csrftoken=([^;]+)/)?.[1] || '' axios.defaults.headers.common['X-CSRFToken'] = csrfToken
三、CORS和CSRF配置为啥没生效?
- CORS_ORIGIN_WHITELIST(Django 3.2+已经改成
CORS_ALLOWED_ORIGINS)管的是跨域请求能不能发,和CSRF验证是两码事——它不负责帮你带CSRF Token - CSRF_TRUSTED_ORIGINS必须写完整的域名(带协议和端口),比如前端是
http://localhost:8080,后端就得写http://localhost:8080,不能只写localhost;生产环境要带https:// - 必须开
CORS_ALLOW_CREDENTIALS = True,不然哪怕CORS白名单配对了,Cookie也不会被带到跨域请求里 - 检查
SESSION_COOKIE_DOMAIN和CSRF_COOKIE_DOMAIN:如果是子域名跨域(比如前端app.example.com,后端api.example.com),得把这俩设成.example.com(前面带点),让Cookie能跨子域名共享
四、额外要查的点
- 浏览器隐私设置:如果开了“阻止第三方Cookie”,跨域请求根本带不了Cookie,配置再对也没用
- 对比备份版本的
package.json:看看Axios是不是被意外升级了——有些版本更新会改默认的CSRF逻辑 - 浏览器插件:广告拦截器、隐私插件可能会屏蔽Cookie的读取或发送,试试禁用插件再测试
内容的提问来源于stack exchange,提问作者crawlingdev
相关产品推荐
相关产品推荐

