如何在用户更改密码或请求重置密码时收到通知?

时间:2012-02-03 17:20:57

标签: django

对于密码更改,我使用auth_views.password_change并重置密码auth_views.password_reset

当用户成功更改密码时,如何通知我?我不需要知道旧密码或新密码。只是事件发生了,以及哪个用户。

同样,我希望在有人要求重置密码时以及成功完成重置程序时收到通知。

我可以通过信号或一些简单的修补来完成上述操作吗?或者我是否需要编写自己的观点才能做到这一点?

5 个答案:

答案 0 :(得分:7)

创建装饰器:

def notify_admins(func):
    def wrapper(request, *args, **kwargs):
        # send email to admins
        return func(request, *args, **kwargs)
    return wrapper

然后,只需将其包装在urls.py中的相应视图中:

urlpatterns = patterns('',
    ...
    (r'^password_change/done/$', notify_admins(auth_views.password_change_done)),
    (r'^password_reset/done/$', notify_admins(auth_views.password_reset_done)),
    (r'^reset/done/$', notify_admins(auth_views.password_reset_complete)),
    ...
)

请记住,直接从视图发送电子邮件,或者在这种情况下是装饰器,会占用请求。不是直接在那里发送电子邮件,最好是创建一个自定义信号和一个处理程序,它将触发一个线程来实际发送电子邮件。然后,在装饰器中,您只需发送信号。

答案 1 :(得分:4)

您可以撰写传递给password_change_form的自定义password_change。此表单将扩展django的PasswordChangeForm覆盖其save方法,以首先通知您更改,然后调用它的父PasswordChangeForm保存方法。

关于password_change视图的文档: https://docs.djangoproject.com/en/dev/topics/auth/#django.contrib.auth.views.password_change

ChangeForm上的文档: https://docs.djangoproject.com/en/dev/topics/auth/#django.contrib.auth.forms.PasswordChangeForm

PasswordChangeForm的代码: https://code.djangoproject.com/browser/django/trunk/django/contrib/auth/forms.py

答案 2 :(得分:3)

从Django 1.9开始,您可以定义自己的密码验证器。如果你愿意,你甚至可以简单地重新定义一个现有的。执行此操作时,请添加方法:

from django.contrib.auth.password_validation import MinimumLengthValidator
class MyPasswordValidator(MinimumLengthValidator):

    def password_changed(self, password, user):
        # put your password changed logic here

请务必在您的设置中添加新课程,如下所示:

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'my_package.password_validators.MyPasswordValidator',
        'OPTIONS': {
            'min_length': 8,
        }
    },
    ...
]

现在,每次用户更改密码时,都会通知您的MyPasswordValidator类。根据我的经验,这是最好的方法,因为:

  1. 当使用信号捕获这些事件时,您还将捕获由于散列参数更改而导致系统重新编码现有密码的事件,在大多数情况下,您不希望捕获这些事件并且没有明显的方法用信号来阻止它。
  2. 您可以在所有密码处理表单的save()方法中简单地添加一个函数调用,但是如果您想对内置的管理员更改密码表单执行相同的操作,这将变得很困难,如果密码更改以编程方式在表单之外进行。
  3. 我会提醒您注意password_changed()中的password参数实际上是用户的原始密码。处理此问题时要小心,绝对不要将其存放在未加密/未加密的地方。

答案 3 :(得分:2)

如果您已经在使用auth_views.password_change内置视图,那么在成功更改后重定向会很容易通知您自己:

https://docs.djangoproject.com/en/dev/topics/auth/#django.contrib.auth.views.password_change

password_change(request[, template_name, post_change_redirect, password_change_form])

如果您将post_change_redirect网址设置为重定向到您自己的某个视图,那么您只需在该视图中执行您想要的任何操作即可发送通知(电子邮件,数据库更新等)。

您甚至可以在重定向视图中执行通知,然后返回password_change_done(request[, template_name])

答案 4 :(得分:1)

您还可以捕获信号并检查密码是否已更改。请记住,每次用户更改时,此代码都会运行。

@receiver(pre_save, sender=User)
def record_password_change(sender, **kwargs):
    user = kwargs.get('instance', None)
    if user:
        new_password = user.password
        try:
            old_password = User.objects.get(pk=user.pk).password
        except User.DoesNotExist:
            old_password = None

        if new_password != old_password:
            # do what you need here