Django - CSRF验证失败

时间:2010-12-28 16:43:03

标签: python django

尝试从教程中创建简单表单时,我收到CSRF验证失败消息。我对CSRF验证实际上做了一些研究,据我所知,为了使用它,你需要在你的html中使用其中一个csrf_token标签,但我没有那个

这是我的模板:

<form action="/testapp1/contact/" method="post">
    {{ form.as_p }}
    <input type="submit" value="Submit" />
</form>

相当简单,位于contact.html

这是我的urlconf: 来自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 个答案:

答案 0 :(得分:34)

修复

<强> 1 即可。在模板中包含{% csrf_token %} 表单标记。

<强> 2 即可。如果由于任何原因您在Django 1.3及更高版本上使用render_to_response,请将其替换为the render function。替换这个:

# 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})

The render function was introduced in Django version 1.3 - 如果您使用的是古老版本like 1.2 or below,则必须使用render_to_responseRequestContext

# Deprecated since version 2.0
return render_to_response('contact.html', {'form': form},
                   context_instance=RequestContext(request))

什么是CSRF保护?为什么我需要它?

这是一种攻击,敌人可以强迫你的用户做一些令人讨厌的事情,比如转移资金,更改他们的电子邮件地址等等:

  

跨站点请求伪造(CSRF)是一种攻击,它强制最终用户在当前对其进行身份验证的Web应用程序上执行不需要的操作。 CSRF攻击专门针对状态更改请求,而不是数据被盗,因为攻击者无法查看对伪造请求的响应。通过社交工程的一些帮助(例如通过电子邮件或聊天发送链接),攻击者可以欺骗Web应用程序的用户执行攻击者选择的操作。如果受害者是普通用户,则成功的CSRF攻击可以强制用户执行状态更改请求,例如转移资金,更改其电子邮件地址等。如果受害者是管理帐户,CSRF可能会危及整个Web应用程序。资料来源:The Open Web Application Security Project

即使您现在不关心此类事情,应用程序也可能会增长,因此最佳做法是保持CSRF保护。

CSRF保护不应该是可选的吗?

它是可选的,但默认情况下处于打开状态(默认情况下包含CSRF中间件)。你可以把它关掉:

  • 通过使用csrf_excempt装饰器进行装饰来获取特定视图。
  • 通过从settings.py 的中间件列表中删除CSRF中间件,为每个视图

如果您在系统范围内将其关闭,可以通过使用csrf_protect装饰器进行装饰来为特定视图启用它。

答案 1 :(得分:3)

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)) 

mytemlate.html:

<form action="/someurls/" method="POST">{% csrf_token %}

答案 2 :(得分:2)

对于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>