React/Vite传CSRF令牌仍触发Django 403错误(CSRF Cookie未设置)
以下是针对问题的具体修复方案,按优先级排序:
1. 修正Django中间件顺序
你的MIDDLEWARE中SessionMiddleware在CsrfViewMiddleware之后,这会导致CSRF验证无法正确关联会话,是引发403错误的核心原因。必须将SessionMiddleware移到CsrfViewMiddleware之前:
MIDDLEWARE = [ 'corsheaders.middleware.CorsMiddleware', 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', # 调整到此处 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', # ... 其他中间件 ... ]
2. 简化前端CSRF获取逻辑
你当前手动从接口返回值提取CSRF token并存入cookie,但@ensure_csrf_cookie装饰器已经会在响应中自动设置csrftoken cookie,无需手动覆盖。修改前端代码如下:
// 仅触发接口让Django设置cookie,无需处理返回值 useEffect(() => { getCSRFToken(); }, []); const getCSRFToken = async () => { const apiUrl = import.meta.env.VITE_API_URL; await fetch(`${apiUrl}getCSRFToken/`, { method: "GET", credentials: "include", }); };
提交表单时保留原有的Cookies.get("csrftoken")逻辑即可。
3. 验证CSRF_TRUSTED_ORIGINS的完整性
确保CSRF_TRUSTED_ORIGINS包含完整的协议、域名和端口,比如前端为https://your-frontend.com:3000,则配置:
CSRF_TRUSTED_ORIGINS = [ env('FRONTEND_URL'), # 确保环境变量是完整URL,如"https://your-frontend.com:3000" ]
本地开发时需写http://localhost:5173而非仅localhost。
4. 检查FormData提交的特殊配置
使用FormData作为请求体时,fetch会自动设置Content-Type为multipart/form-data,此时需注意:
- 不要手动设置
Content-Type头,否则会破坏FormData的边界标识 - 在浏览器开发者工具的网络标签中,确认请求头的
X-CSRFToken与cookie中的csrftoken值完全一致
5. 确认CSRF Cookie属性配置
根据部署场景调整以下配置:
CSRF_COOKIE_SAMESITE = 'None' # 跨域场景必须设为None CSRF_COOKIE_SECURE = True # 仅当前后端都用HTTPS时设为True,本地HTTP开发设为False CSRF_COOKIE_HTTPONLY = False # 允许前端读取cookie,配置正确
本地HTTP开发时CSRF_COOKIE_SECURE必须设为False,否则浏览器不会保存cookie。
内容的提问来源于stack exchange,提问作者Ahendall
相关产品推荐
相关产品推荐

