csrf_exempt无法使用django auth

时间:2013-12-19 19:25:53

标签: django django-rest-framework django-csrf csrf-protection

我正在制作移动应用的后端,并使用Django和Userena进行用户管理。我使用Django REST框架进行登录并注册,一切正常。我现在唯一需要做的就是实现“忘记密码”功能。我想使用已经实现的Userena,但是即使在使用csrf_exempt dectorator之后我也无法摆脱“CSRF令牌丢失或错误”的错误。我在做什么?

urls.py

from django.contrib.auth.views import password_reset
from django.views.decorators.csrf import csrf_exempt
...
urlpatterns = patterns(
    '',
    url(r'^password/mobile/reset/$',
       csrf_exempt(password_reset),
       {'template_name': 'userena/password_reset_form.html',
        'email_template_name': 'userena/emails/password_reset_message.txt',
        'extra_context': {'without_usernames': userena_settings.USERENA_WITHOUT_USERNAMES}
        },
       name='userena_password_mobile_reset'),
)

passowrd_reset_form.html

{% extends 'userena/base_userena.html' %}
{% load i18n %}

{% block title %}{% trans "Reset password" %}{% endblock %}

{% block content %}
<form action="" method="post">
  <fieldset>
    <legend>{% trans "Reset Password" %}</legend>
    {% csrf_token %}
    {{ form.as_p }}
  </fieldset>
  <input type="submit" value="{% trans "Send password" %}" />
</form>
{% endblock %}

1 个答案:

答案 0 :(得分:7)

如果在POST到密码重置视图之前执行GET请求,则会在cookie中获取CSRF令牌,然后您可以在POST请求中发送该令牌。

如果您坚持豁免视图:我认为问题在于CSRF保护应用于password_reset视图的方式。它由csrf_protect明确装饰。

要仔细查看问题,我们假设original_password_reset_viewpassword_resetcsrf_protect没有csrf_exempt(csrf_protect(original_password_reset_view)) # ^^ your code # ^^ the decorator in django.contrib.auth.views 。基本上,你这样做:

CsrfViewMiddleware

并添加csrf_protect(csrf_exempt(csrf_protect(original_password_reset_view))) 的效果,我们得到相当于

csrf_protect

CsrfViewMiddleware只是来自csrf_exempt的{​​{3}}。另一方面csrf_protect middleware-turned-decorator论证。因此,由外部csrf_exempt=True表示的中间件会在视图上看到csrf_protect值并禁用其CSRF投影。它否定了外部 csrf_protect(original_password_reset_view) 。所以我们有:

request.csrf_processing_done = True

视图仍然受到保护。基本上,没有理智的方式。 (一种疯狂的方式:编写一个为该特定URL设置{{1}}的中间件。不要这样做......)