CSRF验证失败。Django上的请求已中止。

59
我正在学习Django 1.3 Web开发,但在登录时遇到了以下错误。
Forbidden (403)
CSRF verification failed. Request aborted.
Help
Reason given for failure:
    CSRF token missing or incorrect.

这是我的settings.py包含的应用程序列表。它完全按照书上所说的方式。

INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    # Uncomment the next line to enable the admin:
    'django.contrib.admin',
    # Uncomment the next line to enable admin documentation:
    # 'django.contrib.admindocs',
    'djangocricket.Cricket',
    'djangocricket.cms'
)

这本书指出,它应该包含django.contrib.auth.views.login,而我正在将其包含在内。
urlpatterns = patterns('',
    # Examples:
    url(r'^$', 'djangocricket.Cricket.views.index', name='default'),
    url(r'^user/(\w+)/$', 'djangocricket.Cricket.views.user_home', name='user home'),
    url(r'^login/$', 'django.contrib.auth.views.login'),
    # url(r'^djangocricket/', include('djangocricket.foo.urls')),

    # Uncomment the admin/doc line below to enable admin documentation:
    #url(r'^admin/doc/', include('django.contrib.admindocs.urls')),

    # Uncomment the next line to enable the admin:
    url(r'^news/', 'djangocricket.cms.views.index', name='index'),
    #url(r'^news/(?P<slug>[^\.]+).html', 'djangocricket.cms.views.detail', name='get_single_news_item'),
    url(r'^admin/', include(admin.site.urls)),
)

我的注册/登录页面是从书上复制粘贴来的。它应该可以使用。

<html>
<head>
    <title>Django Bookmarks - User Login</title>
</head>
<h1>User Login</h1>
{% if form.errors %}
    <p>Your username and password didn't match.
        Please try again.</p>
{% endif %}
<form method="post" action=".">
    <p><label for="id_username">Username:</label>
        {{ form.username }}</p>
    <p><label for="id_password">Password:</label>
        {{ form.password }}</p>
    <input type="hidden" name="next" value="/" />
    <input type="submit" value="login" />
</form>
</body>
</html>

我错过了什么?


1
如果有人需要避免 CSRF 验证(出于某些原因),这篇 Stack Overflow 帖子 可能会有帮助。 - JPG
7个回答

79

你需要在Django模板的form元素中添加{% csrf_token %}模板标签。

这样,模板会渲染一个带有CSRF令牌值的隐藏元素。当Django服务器接收到表单请求时,Django将验证令牌是否与表单中呈现的值匹配。这是为了确保POST请求(即数据更改请求)来自于真实的客户端会话。

了解更多信息,请查看Django文档: https://docs.djangoproject.com/en/dev/ref/csrf/

以下是跨站请求伪造攻击的概述: https://www.owasp.org/index.php/CSRF


12
如果您正在使用 csrf_token 模板标签,但问题仍未解决,请检查 CSRF_COOKIE_DOMAIN 设置。在开发环境中,应将其设置为 None

3
如果您的开发服务器没有 SSL,请同时检查 CSRF_COOKIE_SECURE - Mark
1
在生产中应该是什么值? - mm_

9

我有同样的问题。当我添加了 {% csrf_token %} 后,我解决了这个问题。最终我的代码是这样的:

 <form id='formulario2' method='post' action=''>
      <h3>Enter:</h3>
      {% csrf_token %}


     <input id="id_mesaje" name="mesaje" type="email" placeholder="E-mail"/>
    <input type='submit' name="boton2" value='Suscribete' style="display:inline-block;background-color: #80e174; "/>
 </form>

8

我想在这个话题上提供一些额外的信息。如果你遇到了这种情况,并且你确定令牌已经注入到表单中,视图函数也正确处理了所有问题,但问题仍然存在。请确保没有JavaScript代码禁用输入字段。这种情况曾经发生在我身上,在调试了几个小时后,我终于意识到了这一点。

<input type="hidden" name="csrfmiddlewaretoken" value="pHK2CZzBB323BM2Nq7DE2sxnQoBG1jPl" disabled="">

1
好的观点;当表单提交时,disabled 表单元素的值不会被发送到服务器。 - Mat Gessel

5
在您的POST表单中添加csrf_token:
<form method="post" action=".">
    {% csrf_token %}
    ...
</form>

在Django 4.0中,设置CSRF_TRUSTED_ORIGINS非常重要。 参见此处

0
{% csrf_token %}

在你的表单中添加这个功能对我来说很有效。那么为什么我们要使用跨站点请求伪造呢?

嗯,答案很简单,它只是为你的网页增加了另一个安全层,使得任何恶意用户都无法使用错误的令牌验证请求。


0
在模板中的表单标签后,您必须使用井号格式在模板中放置CSRF令牌。例如{% csrf_token %}。 在任何使用POST表单的模板中,在<form>元素内使用csrf_token标签。如果你不想使用csrf_token,那么可以从主应用程序的设置文件中禁用它。

对于您的模板,只需使用

<form method="post" action=".">
    {% csrf_token %}
 //followed by rest of the tags
</form>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接