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

React向Django后端发起登录POST请求时遇CORS及CSRF验证问题

解决React向Django LoginView发起POST请求的CORS/CSRF问题

核心问题分析

LoginView依赖Django的CSRF验证机制,即使配置了CORS和代理,若前端未正确获取/发送CSRF令牌,或后端Cookie配置不当,就会触发验证失败。

后端(Django)配置调整

  1. 清理重复配置
    新版django-cors-headers使用CORS_ALLOWED_ORIGINS,旧版的CORS_ORIGINS_WHITELIST可以删除,避免配置冲突。
  2. 确认中间件顺序
    确保CorsMiddleware在CommonMiddleware之前,settings.py的MIDDLEWARE数组需按此顺序排列:
    MIDDLEWARE = [
        'corsheaders.middleware.CorsMiddleware',
        'django.middleware.common.CommonMiddleware',
        # 其他中间件...
        'django.middleware.csrf.CsrfViewMiddleware',
        # 其他中间件...
    ]
    
  3. 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)请求配置

  1. 使用代理路径发起请求
    因为已配置React代理,直接用相对路径发起请求,不要写全量后端URL:
    // 正确写法
    fetch('/accounts/login/', { /* 请求配置 */ })
    // 错误写法
    fetch('http://localhost:8000/accounts/login/', { /* 请求配置 */ })
    
  2. 确保请求携带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;
      }
      
  3. 预获取CSRF Cookie
    如果页面加载后未自动获取到csrftoken Cookie,可在页面初始化时发起一个GET请求触发后端设置Cookie:
    // 页面初始化时执行
    async function initCsrf() {
      await fetch('/accounts/login/', { method: 'GET', credentials: 'include' });
    }
    

排查验证步骤

  1. 打开浏览器控制台,进入Application > Cookies > http://localhost:3000,确认存在csrftoken Cookie。
  2. 查看登录POST请求的Request Headers,确认:
    • 包含Cookie: csrftoken=xxx
    • 包含X-CSRFToken: xxx
  3. 检查请求的Content-Type是否为application/x-www-form-urlencoded,LoginView默认不处理JSON格式的请求体。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 12:01:34