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

已在模板中加入CSRF token仍提示缺失?Django AJAX登录问题求助

问题原因

你遇到的CSRF验证失败,核心问题是AJAX请求的数据格式和Django的CSRF验证逻辑不匹配:

  • 你用JSON.stringify()把数据转成了JSON字符串,但Django的request.POST仅处理application/x-www-form-urlencoded(普通表单编码)或multipart/form-data格式的请求体,无法直接解析JSON数据,导致CSRF token无法被识别。
  • 即使你把CSRF token放在JSON参数里,Django的CSRF中间件也无法从JSON中读取到这个token进行验证。
解决方案

有两种可行的修正方式,根据你的需求选择:

方式一:保持表单编码格式提交(推荐,无需修改视图)

直接去掉JSON.stringify(),让jQuery自动把数据编码成普通表单格式,和常规表单提交一致:

$(function(){
    $(document).on('submit', 'form', function(event){
        event.preventDefault();
        $.ajax({
            type: 'POST',
            url: 'login',
            // 直接传递键值对对象,jQuery默认编码为application/x-www-form-urlencoded
            data: {
                username: $('input[name=username]').val(),
                password: $('input[name=password]').val(),
                csrfmiddlewaretoken: $('input[name=csrfmiddlewaretoken]').val()
            },
            success: function(response){
                console.log(response);
            }
        });
    });
});

这种方式下,你的原有视图代码不需要修改,request.POST能正常获取所有参数,CSRF验证也会自动通过。

方式二:使用JSON格式提交(需同步修改视图)

如果必须用JSON格式传递数据,需要同时修改前端和后端:

前端修改

  • 设置contentType: 'application/json'声明请求体格式
  • 将CSRF token放到X-CSRFToken请求头中(Django的CSRF中间件会检查这个请求头)
$(function(){
    $(document).on('submit', 'form', function(event){
        event.preventDefault();
        $.ajax({
            type: 'POST',
            url: 'login',
            contentType: 'application/json', // 声明请求体为JSON
            headers: {
                // 把CSRF token放到请求头
                'X-CSRFToken': $('input[name=csrfmiddlewaretoken]').val()
            },
            data: JSON.stringify({
                username: $('input[name=username]').val(),
                password: $('input[name=password]').val()
            }),
            success: function(response){
                console.log(response);
            }
        });
    });
});

后端视图修改

因为request.POST无法解析JSON数据,需要手动解析request.body:

import json
from django.contrib import auth
from django.http import HttpResponse

def login(request):
    if request.method == "POST":
        # 解析JSON格式的请求体
        data = json.loads(request.body)
        username = data["username"]
        password = data["password"]
        user = auth.authenticate(username=username, password=password)
        if user:
            auth.login(request, user)
            return HttpResponse("Successfully logged in!")
        else:
            return HttpResponse("Username or Password is incorrect")
    else:
        return render(request, "login.html")
补充说明
  • 你尝试的手动传递CSRF token到模板的方法是可行的,只要模板中正确渲染<input type="hidden" name="csrfmiddlewaretoken" value="{{ csrf_token }}">,和使用{% csrf_token %}效果完全一致,问题不在token的传递,而是AJAX的提交格式。
  • CSRF Cookie值保持不变是正常现象,它的默认有效期是浏览器会话周期,只要浏览器不关闭,Cookie值不会主动变化,这不是导致验证失败的原因。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 16:52:45