Django升级至最新版后提交表单出现CSRF验证失败(403)求助
Django升级后CSRF验证失败问题解决
问题背景
基于Django 3.8开发的答题应用,升级到最新版本后,学生提交答案时抛出CSRF verification failed. Request aborted错误,提示CSRF token缺失。已添加{% csrf_token %}标签、配置CsrfViewMiddleware、尝试@csrf_protect装饰器均无效。
错误原因分析
- 模板冗余CSRF输入:模板同时存在
{% csrf_token %}和手动硬编码的固定值csrfmiddlewaretoken隐藏输入,静态token无法随请求动态更新,导致验证失效。 - JS函数逻辑错误:
saveAns函数中使用if(ele[i].type="radio")(赋值运算符)而非判断运算符===,会强制将所有input元素的type改为radio,包括{% csrf_token %}生成的隐藏输入框,破坏了CSRF token的提交结构。 - 视图请求处理不规范:视图未限定仅处理POST请求,且依赖Cookie获取答案的方式不符合Django CSRF验证的规范流程。
解决方案
1. 清理模板冗余代码
移除模板中手动添加的固定CSRF token输入,保留{% csrf_token %}即可,该标签会自动生成动态有效的token:
<!-- 删除以下硬编码内容 --> <!-- <input type="hidden" name="csrfmiddlewaretoken" value="C24rUotmdHawVQJL3KrqiWxvti8UffOFYUc8TRbZtLt36AVLdP3jbkzUVe3beRAa"> -->
2. 修复JS函数判断逻辑
将saveAns中的赋值操作改为全等判断,避免修改非radio输入的类型,同时确保函数返回true以保证表单正常提交:
function saveAns(){ var ele = document.getElementsByTagName('input'); for(i = 0; i < ele.length; i++) { // 改为全等判断 === if(ele[i].type === "radio") { if(ele[i].checked){ setCookie(ele[i].name,ele[i].value,3) } } } return true; }
3. 规范视图请求处理
更新视图,仅在POST请求时处理逻辑,同时建议直接从request.POST获取答案(更安全,避免Cookie依赖):
from django.shortcuts import HttpResponseRedirect, get_object_or_404 from django.contrib.auth.decorators import login_required @login_required def calculate_marks_view(request): # 仅处理POST请求 if request.method == 'POST': course_id = request.COOKIES.get('course_id') if course_id is None: return HttpResponseRedirect('/student/') course = get_object_or_404(QMODEL.Course, id=course_id) total_marks = 0 questions = QMODEL.Question.objects.filter(course=course) # 从request.POST获取选中答案,替代Cookie方式 for idx, question in enumerate(questions, 1): selected_ans = request.POST.get(str(idx)) if selected_ans == question.answer: total_marks += question.marks student = get_object_or_404(Student, user_id=request.user.id) result = QMODEL.Result.objects.create( marks=total_marks, exam=course, student=student ) return HttpResponseRedirect('view-result') # GET请求重定向到考试页面 return HttpResponseRedirect('/student/exam/')
额外注意事项
- 确保渲染表单的视图通过
render(request, template_name, context)传递request对象,这样{% csrf_token %}才能生成正确的token。 - 升级Django后,检查
CSRF_COOKIE_SECURE、CSRF_COOKIE_HTTPONLY等设置,若站点使用HTTPS,建议开启CSRF_COOKIE_SECURE。
内容的提问来源于stack exchange,提问作者The Dance Studio
相关产品推荐
相关产品推荐

