Django密码重置通过电子邮件

时间:2016-09-16 19:46:44

标签: python django django-forms

我尝试通过向用户发送电子邮件来实施密码重置,该链接会将他/她重定向到新密码表单。

我举了示例this questionthis site

但我的问题有点不同。我没有包含用户的本地数据库,因此我无法对其属性执行操作。我通过API(用户ID,用户电子邮件,用户密码)接收用户数据。

那么,这是生成唯一链接以通过电子邮件发送给用户的最佳方式,以便此链接告诉我该用户并允许我重设他/她的密码?而且,我怎么能在 urls.py 中重定向它? 我希望这个链接只能使用一次。

我的views.py是这样的:

def password_reset_form(request):

if request.method == 'GET':
    form = PasswordResetForm()
else:
    form = PasswordResetForm(request.POST) 

    if form.is_valid():
        email = form.cleaned_data['email']

        content_dict = {
            'email': email,
            'domain': temp_data.DOMAIN,
            'site_name': temp_data.SITE_NAME,
            'protocol': temp_data.PROTOCOL,
            }

        subject = content_dict.get('site_name')+ ' - Password Reset'
        content = render_to_string('portal/password_reset_email.html', content_dict)
        send_mail(subject, content, temp_data.FIBRE_CONTACT_EMAIL, [email])

        return render(request, 'portal/password_reset_done.html', {'form': form,})

return render(request, 'portal/password_reset_form.html', {'form': form,})

我发送的电子邮件模板是:

{% autoescape off %}

You're receiving this e-mail because we got a request to reset the password for your user account at {{ site_name }}.

Please go to the following page and choose a new password:

{% block reset_link %}
{{ protocol }}://{{ domain }}/[***some unique link***]
{% endblock %}

If you didn't request a password reset, let us know. 

Thank you.

The {{ site_name }} team.

{% endautoescape %}

谢谢,伙计们。

3 个答案:

答案 0 :(得分:1)

我建议借用Django的一般逻辑并根据你的具体情况进行调整:

PasswordResetTokenGenerator._make_token_with_timestamp()可以看出,它的算法依赖于用户的上次登录时间戳,因此您使用的API需要适应这一点。

您可以导入上述使用的相同实用程序功能 - 在加密方面,最好依靠经过充分测试的解决方案。当你更新到更新的Django版本时,深层内部很容易在没有发行说明的情况下发生变化,所以要小心。

您还可以考虑简单地将一些经过仔细随机生成的重置代码与用户名一起存储在本地数据库中,并在用户访问重置表单时将其删除,但这样不那么优雅,同时更容易发生脆弱和信息安全问题。

答案 1 :(得分:1)

问题不是生成唯一链接,您需要存储有关用户ID或电子邮件以及生成令牌的某处信息。否则,您将不知道哪个用户应该使用哪个令牌。用户重置密码后,您可以删除他的记录(他的令牌)。

你甚至可以在sqlite中编写最简单的模型,基本上看起来像这样:

class UserTokens(model.Models):
    email = models.EmailField(max_length=50)
    token = models.CharField(max_length=50)

之后当您发送邮件时,请执行以下操作:

def password_reset_form(request):

    #your logic here
    # form post

    usr, created = UserToken.objects.get_or_create(email=form.email)
    if usr.token:
        #send this token to him
     else:
        usr.token = ''.join(
    random.choice(string.ascii_uppercase + string.digits) for _ in range(50))
         usr.save()
         #also send this token to him

然后创建一个新视图或api视图,搜索该标记,如果找到,则让他重置密码。如果没有,请提出404错误,或者只是让他知道没有这样的链接来重置密码。

请注意,这是用我的手机写的,所以要小心打字错误。

PS。你还询问了网址

就这样做:

url(r'unsubscribe/(?P<quit_hash>[\w\d]+)/$', 'quit_newsletter_or_somethin', name='quit_newsletter_or_somethin')

答案 2 :(得分:1)

不要重新发明轮子。你应该使用django-allauth这种东西。图书馆维护良好,正在积极开发中。