Django提交表单时遇到403错误:CSRF verification failed

在学习Django框架提交表单时,遇到了403错误,详细信息如下:

Forbidden (403)
CSRF verification failed. Request aborted.
You are seeing this message because this site requires a CSRF cookie when submitting forms. This cookie is required for security reasons, to ensure that your browser is not being hijacked by third parties.
If you have configured your browser to disable cookies, please re-enable them, at least for this site, or for 'same-origin' requests.
Help
Reason given for failure:
    CSRF cookie not set.
    
In general, this can occur when there is a genuine Cross Site Request Forgery, or when Django's CSRF mechanism has not been used correctly. For POST forms, you need to ensure:
1. Your browser is accepting cookies.
2. The view function passes a request to the template's render method.
3. In the template, there is a {% csrf_token %} template tag inside each POST form that targets an internal URL.
4. If you are not using CsrfViewMiddleware, then you must use csrf_protect on any views that use the csrf_token template tag, as well as those that accept the POST data.
5. The form has a valid CSRF token. After logging in in another browser tab or hitting the back button after a login, you may need to reload the page with the form, because the token is rotated after a login.

根据提示依次check一遍:

1. 我的浏览器是开启了cookie的,没毛病;

2. 我的view.py中的代码是这样的:

#coding=utf-8
from django.shortcuts import render, render_to_response

#表单
class UserForm(forms.Form):
    username = forms.CharField(label='用户名',max_length=20)
    password = forms.CharField(label='密码',widget=forms.PasswordInput())

def register(request):
    if request.method == 'POST':
        uf = UserForm(request.POST)
        if uf.is_valid():
            #获得表单数据
            username = uf.cleaned_data['username']
            password = uf.cleaned_data['password']
            #添加到数据库
            User.objects.create(username= username,password=password)
            return HttpResponse('Register success!!')
        else:
            return HttpResponse('Register failed!!')
    else:
        uf = UserForm()
        return render_to_response('register.html',  context=RequestContext(request, {'uf':uf}))

这段代码是从网上拷贝的,这里也确实使用了RequestContext,并且将request传给RequestContext了,好像也没什么问题。

3. 我的模板内容是这样的:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>注册</title>
</head>

<body>
<h1>注册页面:</h1>
<form method="post" enctype="multipart/form-data">
    {% csrf_token %}
    {{uf.as_p}}
    <input type="submit" value = "注册" />
</form>
<br>
<a href="/login/">登陆</a>
</body>
</html>
模板中也确实用了"{% csrf_token %}",好像也没什么问题。

4. 中间件CsrfViewMiddleware在工程创建的就默认加入了,也没毛病。

5. 第一次提交表单的时候就出现了403错误,都没有后退的机会,该项也可以忽略。

又额外查看了两点:

1. 后台服务器打印出如下日志:

UserWarning: A {% csrf_token %} was used in a template, but the context did not provide the value.  This is usually caused by not using RequestContext.

2. 查看浏览器的cookie

我是用的chrome浏览器,安装插件Web Developer,可以看到该网页确实没有设置任何cookie。


可以看到页面的cookie没有设置成功,而设置cookie在check列表的第2项完成,本机安装的Django是1.10版本,而拷贝的这段代码是在1.10之前的版本下运行的,猜测可能是方法render_to_response导致的,改用render方法:

def register(request):
    if request.method == 'POST':
        uf = UserForm(request.POST)
        if uf.is_valid():
            #获得表单数据
            username = uf.cleaned_data['username']
            password = uf.cleaned_data['password']
            #添加到数据库
            User.objects.create(username= username,password=password)
            return HttpResponse('Register success!!')
        else:
            return HttpResponse('Register failed!!')
    else:
        uf = UserForm()
        return render(request, 'register.html', Context({'uf':uf}))
结果可以正常工作了,通过Web Developer可以看到cookie "csrftoken"被页设置成功了:




  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值