51Testing软件测试论坛

标题: Forbidden (403) CSRF verification failed. Request aborted. [打印本页]

作者: yilisong007    时间: 2018-8-21 15:55
标题: Forbidden (403) CSRF verification failed. Request aborted.
在学习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"被页设置成功了:
最后总结一下:我这边的话是在html里面添加了"{% csrf_token %}"就可以了[attach]118110[/attach]

作者: yilisong007    时间: 2018-8-21 15:56
https://blog.csdn.net/cauwu/article/details/52971819(详细好看的界面)




欢迎光临 51Testing软件测试论坛 (http://bbs.51testing.com/) Powered by Discuz! X3.2