Django - CSRF 验证失败
我在尝试根据一个教程制作简单表单时,遇到了“CSRF验证失败”的提示。我查了一下CSRF验证到底是什么,了解到要使用它,你的HTML里需要有一个csrf_token标签,但我没有这个。
这是我的模板:
<form action="/testapp1/contact/" method="post">
{{ form.as_p }}
<input type="submit" value="Submit" />
</form>
这个模板很简单,位于contact.html。
这是我的url配置:
from django.conf.urls.defaults import *urlpatterns=patterns('testapp1.views',
(r'^$', 'index'),
(r'^contact/$','contact')
)
我的应用名称是testapp1。当我输入网址(http://localhost:8000/testapp1/contact)时,可以正常打开表单。但是当我提交表单时,就出现了验证错误。
这是我的视图代码,虽然我觉得这可能不太相关:
def contact(request):
if request.method == 'POST': # If the form has been submitted...
form = ContactForm(request.POST) # A form bound to the POST data
if form.is_valid(): # All validation rules pass
subject = form.cleaned_data['subject']
message = form.cleaned_data['message']
sender = form.cleaned_data['sender']
cc_myself = form.cleaned_data['cc_myself']
recipients = ['info@example.com']
if cc_myself:
recipients.append(sender)
print 'Sending Mail:'+subject+','+message+','+sender+','+recipients
return HttpResponseRedirect('/thanks/') # Redirect after POST
else:
form = ContactForm() # An unbound form
return render_to_response('contact.html', {
'form': form,
})
3 个回答
针对Django 1.4
版本
设置文件:settings.py
MIDDLEWARE_CLASSES = (
...
'django.middleware.csrf.CsrfViewMiddleware',
)
视图文件:view.py
from django.template.defaulttags import csrf_token
from django.shortcuts import render
@csrf_token
def home(request):
"""home page"""
return render(request,
'template.html',
{}
)
模板文件:template.html
<form action="">
{% csrf_token %}
....
</form>
views.py:
from django.shortcuts import render_to_response
from django.template import RequestContext
def my_view(request):
return render_to_response('mytemplate.html', context_instance=RequestContext(request))
mytemplate.html:
<form action="/someurls/" method="POST">{% csrf_token %}
解决方法
1. 在模板中的表单标签里加上 {% csrf_token %}
。
2. 如果你在使用 Django 1.3 及以上版本,并且出于某种原因使用了 render_to_response
,那么要把它换成 render
函数。把下面这个:
# Don't use this on Django 1.3 and above
return render_to_response('contact.html', {'form': form})
换成这个:
return render(request, 'contact.html', {form: form})
render
函数是在 Django 1.3 版本中引入的 - 如果你使用的是很老的版本 比如 1.2 或更早的版本,你必须使用 render_to_response
并且需要一个 RequestContext
:
# Deprecated since version 2.0
return render_to_response('contact.html', {'form': form},
context_instance=RequestContext(request))
什么是 CSRF 保护,为什么我需要它?
CSRF 是一种攻击方式,攻击者可以强迫你的用户做一些不好的事情,比如转账、修改邮箱地址等等:
跨站请求伪造(CSRF)是一种攻击,强迫用户在他们已经登录的网页应用上执行不想要的操作。CSRF 攻击主要针对那些会改变状态的请求,而不是窃取数据,因为攻击者无法看到伪造请求的响应。通过一些社交工程手段(比如通过邮件或聊天发送链接),攻击者可能会欺骗网页应用的用户执行他们想要的操作。如果受害者是普通用户,成功的 CSRF 攻击可以迫使用户执行改变状态的请求,比如转账、修改邮箱地址等。如果受害者是管理员账户,CSRF 攻击可能会危及整个网页应用。来源:开放网页应用安全项目
即使你现在不在乎这些,应用可能会发展壮大,所以最好的做法是保持 CSRF 保护开启。
CSRF 保护不应该是可选的吗?
CSRF 保护是可选的,但默认是开启的(CSRF 中间件默认包含)。你可以关闭它:
- 通过给特定视图加上
csrf_exempt
装饰器。 - 通过从
settings.py
的中间件列表中移除 CSRF 中间件,来对所有视图关闭。
如果你在系统范围内关闭了它,可以通过给特定视图加上 csrf_protect
装饰器来重新开启。