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

Django与AJAX交互时CSRF Token无效问题求助

解决Django跨域AJAX请求的CSRF Token错误问题

首先咱们明确核心问题:你的请求是跨域场景(React在3000端口,Django在8000端口),虽然禁用了Chrome的跨源检查,但这会导致Cookie和Token的处理逻辑异常,再加上当前请求头里的X-CSRFToken和Cookie中的csrftoken值不一致,直接触发了Django的CSRF验证失败。下面是具体的解决步骤:

1. 用正规CORS配置替代浏览器跨源检查

禁用浏览器跨源检查只是临时调试方案,正规做法是让Django支持跨域请求并允许Cookie传递:

  • 先安装django-cors-headers依赖:
    pip install django-cors-headers
    
  • 在settings.py中添加配置:
    INSTALLED_APPS = [
        # ... 其他已安装应用
        'corsheaders',
    ]
    
    MIDDLEWARE = [
        'corsheaders.middleware.CorsMiddleware',  # 必须放在CsrfViewMiddleware之前
        'django.middleware.common.CommonMiddleware',
        # ... 其他中间件
        'django.middleware.csrf.CsrfViewMiddleware',
        # ...
    ]
    
    # 允许你的React应用域名
    CORS_ALLOWED_ORIGINS = [
        "http://localhost:3000",
    ]
    
    # 允许跨域请求携带Cookie(关键配置)
    CORS_ALLOW_CREDENTIALS = True
    

2. 确保CSRF Token的获取与发送完全一致

你当前的核心矛盾是请求头Token和Cookie Token不匹配,这是因为前端没有正确读取最新的Cookie Token:

  • 先给用来获取CSRF Token的初始GET视图添加@ensure_csrf_cookie装饰器,确保Django能给前端设置CSRF Cookie:
    from django.views.decorators.csrf import ensure_csrf_cookie
    from django.http import JsonResponse
    
    @ensure_csrf_cookie
    def init_csrf(request):
        return JsonResponse({"status": "ready"})
    
  • 修改前端AJAX的Token获取逻辑,直接从Cookie中读取当前有效的csrftoken:
    // 封装Cookie读取函数
    function getCookie(name) {
        let cookieValue = null;
        if (document.cookie && document.cookie !== '') {
            const cookies = document.cookie.split(';');
            for (let i = 0; i < cookies.length; i++) {
                const cookie = cookies[i].trim();
                if (cookie.substring(0, name.length + 1) === (name + '=')) {
                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                    break;
                }
            }
        }
        return cookieValue;
    }
    
    // AJAX请求配置
    $.ajax({
        url: "/login/",
        method: "POST",
        data: {username: "xxx", password: "xxx"},
        beforeSend: function (xhr, settings) {
            if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
                const csrftoken = getCookie('csrftoken');
                xhr.setRequestHeader("X-CSRFToken", csrftoken);
            }
        },
        // 跨域必须开启这个,否则Cookie不会被发送到后端
        xhrFields: {
            withCredentials: true
        },
        crossDomain: true,
        success: function(res) {
            console.log(res);
        }
    });
    

3. 验证请求的Token一致性

修改完成后,重新发起请求,检查请求头:

  • 确保Cookie字段中包含csrftoken,且X-CSRFToken的值和它完全相同
  • 确认请求头的Origin是http://localhost:3000,且已在Django的CORS_ALLOWED_ORIGINS中配置

4. 完善Django登录视图的异常处理

你的登录视图目前没有处理认证失败的情况,建议补充完整避免500错误:

from django.http import JsonResponse
from django.contrib.auth import authenticate

def login(request, *args, **kwargs):
    if request.method != 'POST':
        return JsonResponse({"error": "Method not allowed"}, status=405)
    
    username = request.POST.get('username')
    password = request.POST.get('password')
    user = authenticate(request, username=username, password=password)
    
    if user is not None:
        return JsonResponse({"user_id": user.id}, status=200)
    else:
        return JsonResponse({"error": "Invalid username or password"}, status=401)

最后记得重启Django服务,清除浏览器缓存和Cookie后重新测试,应该就能解决CSRF Token不匹配的问题了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 06:41:42