我想重置/取消设置我的用户的密码,他们应该被迫使用“密码重置”,并设置一个新的,与新的密码验证器验证。我找到了Django文档,所以set_unusable_password()不是一个选项,因为之后不允许重置。我发现使用user.password = ''可以工作-用户无法登录,密码重置可以工作。尽管如此,这个解决方案还是有点笨拙,而且我找不到任何关于这个主题的真实的资源-它的安全性如何,等等?
set_unusable_password()
user.password = ''
f1tvaqid1#
您说得对,使用User.set_unusable_password后无法重置密码。来自https://docs.djangoproject.com/en/4.0/topics/auth/default/#django.contrib.auth.views.PasswordResetView:标记为不可用密码的用户(请参阅set_unusable_password())不允许请求密码重置,以防止在使用外部身份验证源(如LDAP)时误用密码。
User.set_unusable_password
解决方案1 -覆盖默认Django行为
使用View和Form类来覆盖django.contrib.auth.forms.PasswordResetForm.get_users,django.contrib.auth.forms.PasswordResetForm.get_users是Django方法,它获取给定电子邮件地址的User示例。重新实现它而不使用if user.has_usable_password条件,这样你就可以真正利用User.set_unusable_password方法。这样,您就可以使用Django内部使用的规范,而“无效”的密码永远无法与外部输入匹配。
django.contrib.auth.forms.PasswordResetForm.get_users
User
if user.has_usable_password
解决方案2 -无或空字符串
正如您提到的,使用None值或空字符串应该可以工作。我看到的主要缺点是,如果在身份验证逻辑中引入代码错误/回归,它可能会接受空/空白密码并将它们与DB值匹配。攻击者将获得这些帐户的访问权限。例如,如果用户输入的字符串只包含不允许的字符,验证逻辑接受它,因为它是非空的,然后删除所有无效字符。或者用户输入的字符串只包含空格,这些空格被接受,但后来被删除。在这两种情况下,它都可能导致空字符串,实际上将根据用户的密码测试该字符串,匹配并连接用户。(and当然,还有很多解决方案可以起作用:))顺便说一句,关于Django2.1的一个有趣的注解,请参见https://docs.djangoproject.com/en/4.0/releases/2.1/#miscellaneous:用户.具有可用密码()和密码可用如果密码为None或空字符串,则()函数不再返回False,或者如果密码使用了不在PASSWORD_HASHERS设置中的hasher。这个未记录的行为是Django 1.6中的退化,阻止了使用这样密码的用户请求密码重置。审计您的代码以确认您对这些API的使用不依赖于旧的行为。所以如果你使用Django〈1.6或〉=2.1,你就必须处理它。
None
1条答案
按热度按时间f1tvaqid1#
您说得对,使用
User.set_unusable_password
后无法重置密码。来自https://docs.djangoproject.com/en/4.0/topics/auth/default/#django.contrib.auth.views.PasswordResetView:标记为不可用密码的用户(请参阅set_unusable_password())不允许请求密码重置,以防止在使用外部身份验证源(如LDAP)时误用密码。
解决方案1 -覆盖默认Django行为
使用View和Form类来覆盖
django.contrib.auth.forms.PasswordResetForm.get_users
,django.contrib.auth.forms.PasswordResetForm.get_users
是Django方法,它获取给定电子邮件地址的User
示例。重新实现它而不使用if user.has_usable_password
条件,这样你就可以真正利用User.set_unusable_password
方法。这样,您就可以使用Django内部使用的规范,而“无效”的密码永远无法与外部输入匹配。
解决方案2 -无或空字符串
正如您提到的,使用
None
值或空字符串应该可以工作。我看到的主要缺点是,如果在身份验证逻辑中引入代码错误/回归,它可能会接受空/空白密码并将它们与DB值匹配。攻击者将获得这些帐户的访问权限。例如,如果用户输入的字符串只包含不允许的字符,验证逻辑接受它,因为它是非空的,然后删除所有无效字符。或者用户输入的字符串只包含空格,这些空格被接受,但后来被删除。在这两种情况下,它都可能导致空字符串,实际上将根据用户的密码测试该字符串,匹配并连接用户。
(and当然,还有很多解决方案可以起作用:))
顺便说一句,关于Django2.1的一个有趣的注解,请参见https://docs.djangoproject.com/en/4.0/releases/2.1/#miscellaneous:
用户.具有可用密码()和密码可用如果密码为None或空字符串,则()函数不再返回False,或者如果密码使用了不在PASSWORD_HASHERS设置中的hasher。这个未记录的行为是Django 1.6中的退化,阻止了使用这样密码的用户请求密码重置。审计您的代码以确认您对这些API的使用不依赖于旧的行为。
所以如果你使用Django〈1.6或〉=2.1,你就必须处理它。