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

Django生产环境X-CSRFToken设置错误及CSRF令牌获取问题求助

解决Django+React生产环境CSRF验证失败问题及令牌获取方案

问题背景

  • 本地环境:Django后端通过ensure_csrf_cookie装饰器的接口返回CSRF令牌,React前端存入Cookie后,POST请求携带X-CSRFToken,Cookie与请求头令牌匹配,请求正常。
  • 生产环境:请求头的Cookie字段被转为小写,出现CSRF verification failed错误,提示X-Csrftoken HTTP头令牌不正确。
  • 需求补充:明确浏览器Application面板无CSRF令牌时的正确获取流程。

现有代码

后端Django代码

from django.views.decorators.csrf import ensure_csrf_cookie
from django.utils.decorators import method_decorator
from django.http import JsonResponse
from django.middleware.csrf import get_token

class CSRFTokenView(View):
    @method_decorator(ensure_csrf_cookie)
    def get(self, request, format=None):
        return JsonResponse({'csrftoken':get_token(request)})

前端React代码

import axios from 'axios';
import Cookies from 'js-cookie';
import { useEffect, useState } from 'react';
import { redirect } from 'react-router-dom';

const Signup = () => {
    const [signup, setSignup] = useState({});
    const [disabled, setDisabled] = useState(false);
    const [isUp, setIsUp] = useState(false);
    const [error, setError] = useState({});

    useEffect(()=>{
        axios.get('http://127.0.0.1:8000/csrf/').then((res)=>{
            console.log(res.data)
            Cookies.set('csrftoken',res.data.csrftoken)
        })
    },[])

    let handleSubmit = (e) => {
        e.preventDefault();
        axios
            .post("http://127.0.0.1:8000/signup/", signup, {
                withCredentials: true,
                headers: { "X-CSRFToken": Cookies.get("csrftoken") },
            })
            .then((res) => {
                setDisabled(true)
                setIsUp(true)

                setTimeout(()=>{
                    setIsUp(false)
                    redirect('/')
                },3000)
            })
            .catch((e) => {
                console.log(e.response.data)
                let err = e.response.data
                setError(err);
            });
    };

    return (
        // 组件渲染内容
    )
}

解决方案

1. 生产环境CSRF验证失败修复

核心原因

生产环境中部分代理服务器(如Nginx)会自动将请求头字段转为小写,而Django默认优先识别X-CSRFToken驼峰格式;同时手动通过接口返回并设置Cookie的方式,可能与ensure_csrf_cookie自动生成的Cookie产生冲突,或Cookie的安全属性不符合生产环境要求。

修复步骤

  • 后端调整:移除手动返回令牌,依赖装饰器自动设置Cookie
    ensure_csrf_cookie装饰器会自动在响应头中设置csrftoken Cookie,无需手动返回令牌,避免重复设置导致的冲突:

    class CSRFTokenView(View):
        @method_decorator(ensure_csrf_cookie)
        def get(self, request, format=None):
            return JsonResponse({'status': 'csrf_cookie_set'})
    
  • 前端调整:自动提取Cookie,兼容大小写格式
    不再手动存储Cookie,直接从浏览器Cookie中提取令牌,同时兼容大小写的请求头字段:

    // 封装CSRF令牌获取函数
    const getCsrfToken = () => {
        let token = null;
        if (document.cookie) {
            const cookies = document.cookie.split(';').map(c => c.trim());
            for (const cookie of cookies) {
                if (cookie.startsWith('csrftoken=') || cookie.startsWith('CSRFToken=')) {
                    token = cookie.split('=')[1];
                    break;
                }
            }
        }
        return token;
    };
    
    useEffect(() => {
        // 仅触发后端设置Cookie,无需处理返回数据
        axios.get('/csrf/', { withCredentials: true });
    }, []);
    
    let handleSubmit = (e) => {
        e.preventDefault();
        const csrfToken = getCsrfToken();
        axios
            .post("/signup/", signup, {
                withCredentials: true,
                headers: { 
                    "X-CSRFToken": csrfToken,
                    "x-csrftoken": csrfToken // 兼容小写请求头环境
                },
            })
            .then((res) => {
                setDisabled(true);
                setIsUp(true);
                setTimeout(() => {
                    setIsUp(false);
                    redirect('/');
                }, 3000);
            })
            .catch((e) => {
                console.log(e.response.data);
                setError(e.response.data);
            });
    };
    
  • 生产环境Cookie属性配置
    在Django的settings.py中配置符合生产环境的Cookie安全属性:

    CSRF_COOKIE_SECURE = True  # 仅在HTTPS下传输Cookie
    CSRF_COOKIE_SAMESITE = 'Lax'  # 根据跨域需求选择Strict/Lax/None
    CSRF_COOKIE_HTTPONLY = False  # 允许前端读取Cookie(默认值)
    

2. 浏览器无CSRF令牌时的正确获取流程

当浏览器Application面板中无csrftoken Cookie时,按以下步骤操作:

  • 前端发起不带CSRF令牌的GET请求到后端带有ensure_csrf_cookie装饰器的接口(如/csrf/);
  • 后端通过装饰器自动生成并设置csrftoken Cookie到浏览器;
  • 前端后续的POST/PUT/DELETE请求,调用getCsrfToken()函数从Cookie提取令牌,携带X-CSRFToken请求头;
  • 必须确保所有请求配置withCredentials: true,否则Cookie无法被正确传递和存储。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 02:55:29