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

React+Django部署后登录遇CSRF Cookie未设置/验证失败问题求助

React + Django 跨域CSRF认证失败问题解决

问题描述

本地环境下React前端+Django后端运行正常,但前端部署到Heroku(后端本地)或前后端分别部署后,登录POST请求出现以下错误:

  • 前端部署Heroku、后端本地时:Forbidden (CSRF cookie not set.): /login/
  • 前后端都部署后:Forbidden (403) CSRF verification failed. Request aborted.

核心问题分析

  1. 硬编码域名导致跨域:前端所有请求硬编码http://localhost:8000,部署后域名不匹配,浏览器拦截Cookie,CSRF Token无法正常获取传递。
  2. Cookie配置适配不足:生产环境下SameSite、Secure等Cookie安全配置未正确设置,跨域场景下Cookie无法被携带。
  3. Token获取逻辑冗余:已有带@ensure_csrf_cookie的session_view接口,无需单独写getCsrf接口,重复获取易导致Token不一致。

具体修复步骤

1. 前端代码修复

替换硬编码域名,用环境变量适配部署场景

// 定义后端API地址,开发/生产环境自动切换
const API_BASE_URL = process.env.REACT_APP_API_URL || "http://localhost:8000";

// 修改CSRF Token获取逻辑,从Cookie提取更可靠
function getCsrf(){
    fetch(`${API_BASE_URL}/session/`, {
            credentials: "include",
          })
          .then(() => {
            // 从document.cookie中提取csrftoken
            const csrfToken = document.cookie.split('; ')
              .find(row => row.startsWith('csrftoken='))?.split('=')[1] || '';
            setCsrf({csrf: csrfToken});
          })
          .catch((err) => {
            console.log(err);
          })
}

// 修改登录请求地址
const login = (event) => {
    event.preventDefault();
    setIsLoading(true)
    fetch(`${API_BASE_URL}/login/`, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "X-CSRFToken": csrf.csrf,
      },
      credentials: "include",
      body: JSON.stringify({username: username, password: password}),
    })
    // 其余逻辑保持不变
}

// 修改会话校验请求地址
useEffect(() => {
    setIsLoading(true)
    fetch(`${API_BASE_URL}/session/`, {
        credentials: "include",
      })
      .then((res) => res.json())
      .then((data) => {
        if (data.isAuthenticated) {
          setIsAuthenticated(true)
          console.log(data)
        } else {
          setIsAuthenticated(false)
          console.log(data)
          getCsrf()
        }
        setIsLoading(false)
      })
      .catch((err) => {
        console.log(err);
      });
}, [])

说明:Django默认将CSRF Token存在csrftoken Cookie中,直接从document.cookie提取比响应头更可靠。

2. Django后端配置修复

完善settings.py的Cookie与CORS配置

# settings.py

# 生产环境强制开启HTTPS Cookie(必须配合HTTPS部署)
CSRF_COOKIE_SECURE = True
SESSION_COOKIE_SECURE = True

# 跨域场景下SameSite设为None,配合Secure属性使用
CSRF_COOKIE_SAMESITE = 'None'
SESSION_COOKIE_SAMESITE = 'None'

# 信任所有前端部署域名,替换为实际域名
CSRF_TRUSTED_ORIGINS = [
    'https://your-frontend.herokuapp.com',
    'http://localhost:3000',
    # 其他前端域名
]

# 生产环境建议指定允许的CORS源,而非全量开放
CORS_ALLOWED_ORIGINS = [
    'https://your-frontend.herokuapp.com',
    'http://localhost:3000',
]
CORS_ALLOW_CREDENTIALS = True
CORS_EXPOSE_HEADERS = ['Content-Type', 'X-CSRFToken']

简化CSRF逻辑

删除单独的csrf/接口,复用已有的session_view(该接口带@ensure_csrf_cookie装饰器,会自动设置CSRF Cookie)。

3. 部署注意事项

  • 前端环境变量:在Heroku中设置REACT_APP_API_URL为后端实际部署域名(如https://your-django-backend.herokuapp.com)。
  • 后端HTTPS:确保后端使用HTTPS(Heroku默认提供),否则Secure Cookie无法生效。
  • Cookie验证:浏览器控制台查看Application->Cookies,确认csrftoken和sessionid Cookie的Domain、Secure属性符合预期。

验证方法

  1. 部署后检查浏览器控制台是否有跨域错误。
  2. 确认登录请求的X-CSRFToken头携带的Token与csrftoken Cookie值一致。
  3. 登录成功后检查sessionid Cookie是否正常设置,会话保持正常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 04:00:37