我正在制作移动应用程序的后端,并使用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 %}
如果在发布到密码重置视图之前执行GET请求,则会在Cookie中获得CSRF令牌,然后可以在POST请求中发送该CSRF令牌。
如果您坚持要豁免视图:我认为问题在于CSRF保护应用于password_reset
视图的方式。由明确装饰csrf_protect
。
有这个问题仔细一看,让我们假设original_password_reset_view
是password_reset
没有的csrf_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
另一方面,只是简单地设定csrf_exempt=True
其论点。因此,由外部表示的中间件会在视图上csrf_protect
看到该csrf_exempt=True
值,并禁用其CSRF投影。它否定了外部 csrf_protect
。因此,我们有:
csrf_protect(original_password_reset_view)
该视图仍受保护。基本上,没有理智的方法。(一种疯狂的方式:编写request.csrf_processing_done = True
为该特定URL设置的中间件。不要这样做...)
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句