Python 为什么django调用的默认身份验证后端在引发UserModel.DoesNotExist异常后设置_密码?

Python 为什么django调用的默认身份验证后端在引发UserModel.DoesNotExist异常后设置_密码?,python,django,authentication,exception,custom-authentication,Python,Django,Authentication,Exception,Custom Authentication,我正在为django中从AbstractUser继承的自定义用户模型编写自定义身份验证后端。我已经查看了django的默认身份验证后端,并看到用户对象是使用带有UserModel的用户名获取的。\u default\u manager.get\u by_natural\u key(username)authenticate()如下所示 def authenticate(self, username=None, password=None, **kwargs): UserModel

我正在为django中从AbstractUser继承的自定义用户模型编写自定义身份验证后端。我已经查看了django的默认身份验证后端,并看到用户对象是使用带有
UserModel的用户名获取的。\u default\u manager.get\u by_natural\u key(username)
authenticate()如下所示

def authenticate(self, username=None, password=None, **kwargs):
        UserModel = get_user_model()
        if username is None:
            username = kwargs.get(UserModel.USERNAME_FIELD)
        try:
            user = UserModel._default_manager.get_by_natural_key(username)
            if user.check_password(password):
                return user
        except UserModel.DoesNotExist:
            # Run the default password hasher once to reduce the timing
            # difference between an existing and a non-existing user (#20760).
            UserModel().set_password(password)
我已经编写了一个自定义aut后端,但出于好奇,我问这个问题,为什么会在DoesNotExist异常时检查密码

我在authenticate方法中尝试了
ipdb
,并验证了在获得一个不存在的用户的用户名后,控制流转到except块。终端发出了一个
UserModel().set_密码(password)
。由于不确定后台会发生什么,我检查了
auth.models
set\u password()
代码。但它只是引发了一个
NotImplementedError
异常。我不知道这有什么帮助

另外,在自定义身份验证后端的用户模型上执行失败的对象获取操作时,如何
正确引发UserDoesNotExist或django.core.exceptions.ObjectDoesNotExist异常
?其想法是停止执行并向用户提供正确的反馈消息,而不是引发异常并尝试下一个身份验证后端,如settings.py中的authentication_BACKENDS()所示

TIA

您应该阅读以下内容:

当尝试使用django.contrib.auth进行身份验证时,如果用户不存在,则authenticate()函数几乎会立即返回None,而当用户存在时,由于尝试的密码被散列并与存储的密码进行比较,需要更长的时间。这允许攻击者根据身份验证尝试的响应时间推断给定帐户是否存在


该评论准确地解释了原因。如果它立即返回False,那么所需的时间将比不存在的用户少很多。然后,攻击者就可以区分现有用户名和不存在用户名。

感谢您的快速回答@daniel。但set_password如何在不存在的用户上返回None?如前所述,它引发了一个未实现的异常。该代码实例化一个空用户只是为了调用set_password。