You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

跨域环境下Vue Axios与Django后端CSRF验证异常问题

解决跨域下Django+Vue Axios的CSRF验证与Cookie保存问题

我之前也碰到过一模一样的坑,咱们一步步拆解修复:

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. 测试流程

  1. 重启Django服务和前端项目
  2. 先发送一个GET请求到后端任意接口(比如/api/test/),触发Django设置csrftoken和sessionid Cookie
  3. 再发送POST请求,此时Axios会自动携带X-CSRFToken头,Django的@csrf_protect就能正常验证通过了

按照这些步骤调整后,就能既保留CSRF验证,又让前端正常保存和携带Cookie了。

内容的提问来源于stack exchange,提问作者M. N

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 07:12:50