跨域环境下Vue Axios与Django后端CSRF验证异常问题
我之前也碰到过一模一样的坑,咱们一步步拆解修复:
1. 修正Django中间件顺序(核心问题!)
你的中间件顺序有两个致命错误,直接导致Cookie保存和CSRF验证失败:
CorsMiddleware必须尽可能靠前,确保CORS响应头优先被浏览器识别SessionMiddleware必须在CsrfViewMiddleware之前,因为CSRF Token的生成和验证依赖Session
调整后的中间件列表:
MIDDLEWARE_CLASSES = ( 'django.middleware.security.SecurityMiddleware', 'corsheaders.middleware.CorsMiddleware', # 移到最前面(安全中间件之后) 'django.middleware.common.CommonMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', # Session处理在前 'django.middleware.csrf.CsrfViewMiddleware', # CSRF依赖Session,必须在后 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.auth.middleware.SessionAuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', 'django.middleware.gzip.GZipMiddleware', )
2. 配置Django Cookie的跨域兼容属性
跨域场景下,浏览器的SameSite策略会默认阻止Cookie的保存和发送,需要修改Cookie的相关设置:
# settings.py SESSION_COOKIE_SAMESITE = 'Lax' # 跨域场景用Lax即可,HTTPS环境可设为None(需配合Secure) CSRF_COOKIE_SAMESITE = 'Lax' # 如果是HTTPS部署,添加以下两行(强制Cookie仅通过HTTPS传输) # SESSION_COOKIE_SECURE = True # CSRF_COOKIE_SECURE = True # 允许前端读取CSRF Token(可选,Axios会自动从Cookie获取,不需要的话可设为True) CSRF_COOKIE_HTTPONLY = False
3. 简化并优化CORS配置
你的CORS_ALLOW_HEADERS里重复了多个大小写的X-CSRFToken,可以简化为统一的小写,同时确保覆盖必要的请求头:
CORS_ALLOW_HEADERS = ( 'accept', 'accept-encoding', 'authorization', 'content-type', 'dnt', 'origin', 'user-agent', 'x-csrftoken', # 只保留这一个即可,浏览器会自动处理大小写差异 'x-requested-with', ) # 生产环境建议关闭全局允许,指定具体前端域名更安全,比如: # CORS_ORIGIN_WHITELIST = [ # 'http://localhost:8080', # 'https://your-frontend-domain.com', # ] CORS_ALLOW_CREDENTIALS = True # 这个你已经设置了,必须保留,允许跨域携带Cookie
4. 确认Axios配置的细节
你的Axios配置已经基本正确,再补充一个请求拦截器确保CSRF Token被正确携带(可选,但更稳妥):
axios.defaults.headers.get['Accept'] = 'application/json' axios.defaults.headers.post['Content-Type'] = 'application/json' axios.defaults.withCredentials = true // 必须开启,允许跨域请求携带Cookie axios.defaults.xsrfCookieName = 'csrftoken' // 对应Django的CSRF Cookie名称 axios.defaults.xsrfHeaderName = 'X-CSRFToken' // 对应Django期望的请求头名称 // 可选:添加请求拦截器,手动确保CSRF Token存在 axios.interceptors.request.use(config => { if (config.method === 'post') { const csrfToken = document.cookie.match(/csrftoken=([^;]+)/)?.[1]; if (csrfToken) { config.headers['X-CSRFToken'] = csrfToken; } } return config; });
5. 容易忽略的排查点:Chrome Cookie的查看位置
很多人会犯这个错误:跨域的Cookie是存在后端域名下的,不是前端域名!
比如你的前端是localhost:8080,后端是localhost:8000,要在Chrome的Application面板中,切换到localhost:8000的域名下才能看到sessionid和csrftoken Cookie,而不是看localhost:8080的。
6. 测试流程
- 重启Django服务和前端项目
- 先发送一个GET请求到后端任意接口(比如
/api/test/),触发Django设置csrftoken和sessionidCookie - 再发送POST请求,此时Axios会自动携带
X-CSRFToken头,Django的@csrf_protect就能正常验证通过了
按照这些步骤调整后,就能既保留CSRF验证,又让前端正常保存和携带Cookie了。
内容的提问来源于stack exchange,提问作者M. N
相关产品推荐
相关产品推荐

