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")
请求载荷信息

错误信息


问题原因
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
相关产品推荐
相关产品推荐

