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

Django中Ajax请求遇Invalid CSRF/Token缺失问题求助

Django Ajax登录CSRF验证失败排查与解决

我尝试通过Ajax向Django提交登录请求,已在表单中添加{% csrf_token %},且在Ajax请求数据中携带了csrfmiddlewaretoken,但仍出现CSRF验证失败的问题。以下是相关代码及截图:

HTML表单

<form id="frmLogin" method="post">
    {% csrf_token %}
    <input type="text" name="username" />
    <input type="password" autocomplete="false" name="password" />
    <input type="submit" value="Submit" />
</form>

Ajax代码

$("form#frmLogin").validate({
    rules: {
        username: {
            required: true
        },
        password: {
            required: true
        }
    },
    submitHandler: function(form) {
        var data = {
            "username": $(form).find("input[name='username']").val(),
            "password": $(form).find("input[name='password']").val(),
            "csrfmiddlewaretoken": $(form).find("input[name='csrfmiddlewaretoken']").val()
        };      
        $.ajax({
            method: "POST",
            url: "/authenticate/",
            cache: false,
            async: true,
            data: JSON.stringify(data),
            contentType: "application/json; charset=utf-8",
            success: function(response) {                    
                //$(form).remove();
            }
        })
    }
});

Django视图

from django.shortcuts import render
import json
from django.http import JsonResponse

def Authenticate(request):
    if request.method == "POST":
        #loginData = json.loads(request.body)
        #email = userData["email"]
        #password = userData["password"]
        print("ok")
        return JsonResponse({}, status = 200)
    else:
        print("not ok")

请求载荷信息

请求载荷

错误信息

错误信息1
错误信息2


问题原因

Django的CSRF验证机制默认不会从JSON格式的请求体中读取csrfmiddlewaretoken字段。它只会从两种途径获取CSRF令牌:

  • POST表单数据(application/x-www-form-urlencoded格式)
  • 请求头中的X-CSRFToken字段

你当前的Ajax请求将数据序列化为JSON字符串,并设置了contentType: "application/json; charset=utf-8",导致Django无法从请求体中提取CSRF令牌,最终验证失败。

解决方法

方案1:改用表单编码格式提交数据

无需将数据转为JSON,直接传递普通对象,jQuery会自动将其编码为application/x-www-form-urlencoded格式,Django可正常识别csrfmiddlewaretoken:

submitHandler: function(form) {
    var data = {
        "username": $(form).find("input[name='username']").val(),
        "password": $(form).find("input[name='password']").val(),
        "csrfmiddlewaretoken": $(form).find("input[name='csrfmiddlewaretoken']").val()
    };      
    $.ajax({
        method: "POST",
        url: "/authenticate/",
        cache: false,
        async: true,
        data: data, // 直接传递对象,移除JSON.stringify
        // 无需手动设置contentType,jQuery默认使用application/x-www-form-urlencoded
        success: function(response) {                    
            // 处理成功逻辑
        }
    })
}

对应的Django视图通过request.POST获取数据:

def Authenticate(request):
    if request.method == "POST":
        username = request.POST.get("username")
        password = request.POST.get("password")
        print("ok")
        return JsonResponse({}, status=200)
    else:
        print("not ok")
        return JsonResponse({}, status=405)

方案2:在请求头中携带CSRF令牌

若坚持使用JSON格式提交,需将CSRF令牌放入请求头的X-CSRFToken字段:

submitHandler: function(form) {
    var csrfToken = $(form).find("input[name='csrfmiddlewaretoken']").val();
    var data = {
        "username": $(form).find("input[name='username']").val(),
        "password": $(form).find("input[name='password']").val()
    };      
    $.ajax({
        method: "POST",
        url: "/authenticate/",
        cache: false,
        async: true,
        data: JSON.stringify(data),
        contentType: "application/json; charset=utf-8",
        headers: {
            "X-CSRFToken": csrfToken // 添加CSRF令牌到请求头
        },
        success: function(response) {                    
            // 处理成功逻辑
        }
    })
}

此时Django视图需从request.body解析JSON数据:

def Authenticate(request):
    if request.method == "POST":
        login_data = json.loads(request.body)
        username = login_data.get("username")
        password = login_data.get("password")
        print("ok")
        return JsonResponse({}, status=200)
    else:
        print("not ok")
        return JsonResponse({}, status=405)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 01:10:27