【问题标题】:Detect a changed password in Django在 Django 中检测更改的密码
【发布时间】:2017-01-01 04:44:50
【问题描述】:

当用户更改密码时,我想发送一个信号,以便我可以在某些型号上做一些事情。

如何创建此信号?

我查看了用户的post_save 信号:

post_save.connect(user_updated, sender=User)

但是,那里似乎没有任何内容可供我检查密码是否已更改:

def user_updated(sender, **kwargs):
    print(kwargs) # {'created': False, 'raw': False, 'instance': <User: 100002>, 'update_fields': None, 'signal': <django.db.models.signals.ModelSignal object at 0x7ff8862f03c8>, 'using': 'default'}

我还看到有一个password_change_done auth 视图,但我不确定如何使用它。 https://docs.djangoproject.com/en/1.10/topics/auth/default/#built-in-auth-views

有什么想法吗?

【问题讨论】:

    标签: python django django-authentication django-signals


    【解决方案1】:

    您可以使用pre_save 信号。 kwargs['instance'] 将包含 更新密码,您可以通过User.objects.get(id= user.id).password获取旧密码

    @receiver(pre_save, sender=User)
    def user_updated(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
    

    【讨论】:

    • 请注意,这可以很好地将盐或散列算法中的更改检测为密码更改。如果您只需要检测实际的密码更改,则需要挂钩到视图并在散列之前检查新密码。
    • 盐或哈希算法什么时候可以改变?升级方案?
    • @43Tesseracts 较新版本的 Django 更新密码算法/使用的轮数,当用户登录时更新密码以使用较新版本
    【解决方案2】:

    如果您使用的是自定义用户模型,您大概可以与 set_password() 调用相交以在实例上设置标志,然后在信号中获取它的存在:

    from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin
    from django.db.models.signals import post_save
    
    
    class User(AbstractBaseUser, PermissionsMixin):
        def set_password(self, password):
            super(User, self).set_password(password)
            self._set_password = True
    
        @classmethod
        def user_saved(cls, sender, instance, **kwargs):
            if getattr(instance, '_set_password', False):
                # Take action
    
    
    post_save.connect(User.user_saved, sender=User)
    

    【讨论】:

    • 如果您不介意涉及实现细节,您可以查看instance._password。最初始终为None,如果设置了则成为原始密码。
    【解决方案3】:

    我找到了一个解决方案,这样您就不必比较密码哈希,即使密码相同也可能不同。

    @receiver(pre_save, sender=get_user_model())
    def detect_password_change(sender, instance, **kwargs):
        """
        Checks if the user changed his password
        """
        if instance._password is None:
            return
    
        try:
            user = get_user_model().objects.get(id=instance.id)
        except get_user_model().DoesNotExist:
            return
    
        print("password changed")
        # if you get here, the user changed his password
    

    【讨论】:

      猜你喜欢
      • 2016-08-29
      • 2013-03-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-16
      • 2020-03-19
      • 2020-10-15
      相关资源
      最近更新 更多