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

React+Django跨域POST请求CSRF Token验证失败问题求助

Django + React 跨域 CSRF 问题解决指南

第一个问题:能否让API直接使用Cookie中的CSRF Token验证请求?

不行。Django的CSRF防护机制设计就是必须同时存在CSRF Cookie和X-CSRFToken请求头,且两者值匹配才会通过验证。这是因为CSRF攻击中,浏览器会自动携带Cookie到目标域名,但攻击者无法伪造自定义请求头(受同源策略限制),仅靠Cookie验证无法有效抵御CSRF攻击,所以Django不支持仅用Cookie完成CSRF验证。

第二个问题:跨域场景下如何让前端获取CSRF Token并放入请求头?

需要从后端Django配置和前端React代码两方面配合处理:

后端Django配置步骤

  1. 确保CSRF中间件启用
    检查settings.py的INSTALLED_APPS和MIDDLEWARE,确认django.middleware.csrf.CsrfViewMiddleware已存在(默认已启用)。

  2. 配置CORS支持(必须)
    安装django-cors-headers库,然后在settings.py中添加配置:

    # 安装后添加到中间件(要放在CommonMiddleware之前)
    MIDDLEWARE = [
        'corsheaders.middleware.CorsMiddleware',
        'django.middleware.common.CommonMiddleware',
        # 其他中间件...
    ]
    
    # 允许携带跨域Cookie
    CORS_ALLOW_CREDENTIALS = True
    # 指定信任的前端域名(不要用*,避免安全风险)
    CORS_ALLOWED_ORIGINS = [
        "http://localhost:3000",  # 你的React开发服务器地址
        "https://your-frontend-domain.com",  # 生产环境前端地址
    ]
    # 告诉Django信任这些域名的CSRF请求
    CSRF_TRUSTED_ORIGINS = [
        "http://localhost:3000",
        "https://your-frontend-domain.com",
    ]
    
  3. 调整CSRF Cookie属性
    在settings.py中配置Cookie的SameSite和Secure属性,确保跨域场景下浏览器能正常保存并携带:

    # 开发环境(http)用Lax,生产环境(https)可设为None(需配合Secure=True)
    CSRF_COOKIE_SAMESITE = 'Lax'
    # 生产环境启用https时打开,确保Cookie仅通过HTTPS传输
    CSRF_COOKIE_SECURE = False  # 开发环境设为False,生产设为True
    # 确保CSRF Cookie可被前端JS访问(默认就是False,不要改成True)
    CSRF_COOKIE_HTTPONLY = False
    

前端React代码处理

  1. 请求时携带Cookie
    无论用fetch还是axios,都要开启携带跨域Cookie的配置:

    • 用axios的话,全局配置:
      import axios from 'axios';
      // 全局开启携带Cookie
      axios.defaults.withCredentials = true;
      
    • 用fetch的话,每个请求添加credentials: 'include':
      fetch('/api/your-endpoint', {
        method: 'POST',
        credentials: 'include',
        // 其他配置...
      });
      
  2. 获取CSRF Token
    写一个简单函数从Cookie中提取csrftoken:

    function getCsrfToken() {
      const cookieValue = document.cookie
        .split('; ')
        .find(row => row.startsWith('csrftoken='))
        ?.split('=')[1];
      return cookieValue || '';
    }
    
  3. 自动添加X-CSRFToken请求头

    • 用axios可以添加请求拦截器,自动给需要的请求加头:
      axios.interceptors.request.use((config) => {
        // 仅给非GET/HEAD/OPTIONS的请求加CSRF头(Django对这些请求不做CSRF验证)
        if (!['GET', 'HEAD', 'OPTIONS'].includes(config.method?.toUpperCase())) {
          const csrfToken = getCsrfToken();
          if (csrfToken) {
            config.headers['X-CSRFToken'] = csrfToken;
          }
        }
        return config;
      });
      
    • 用fetch的话,手动在请求头中添加:
      fetch('/api/your-endpoint', {
        method: 'POST',
        credentials: 'include',
        headers: {
          'X-CSRFToken': getCsrfToken(),
          'Content-Type': 'application/json',
        },
        body: JSON.stringify(yourData),
      });
      

关键注意事项

  • 不要将CSRF_COOKIE_HTTPONLY设为True,否则前端JS无法读取该Cookie,也就没法添加请求头。
  • 开发环境如果用http协议,CSRF_COOKIE_SAMESITE设为Lax即可;如果是跨不同主域名的场景(比如前端是a.com,后端是b.com),生产环境用https时可以将CSRF_COOKIE_SAMESITE设为None,同时必须开启CSRF_COOKIE_SECURE = True(SameSite=None要求Cookie必须是Secure的)。
  • 登录请求也要开启withCredentials,否则后端设置的CSRF Cookie不会被前端浏览器保存。

内容的提问来源于stack exchange,提问作者gxs629

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 20:33:31