我在使用syncdb
命令时创建了一个用户,并且完美登录。但是当我从django admin创建用户时,它已成功创建但在登录时会导致错误。我收到错误:
Unknown password hashing algorithm 'password'. Did you specify it in the PASSWORD_HASHERS setting?
问题是什么?如何解决此问题,以便在将用户保存为admin时自动加密密码?
答案 0 :(得分:4)
我遇到了同样的问题,我已经将Django的用户子类化,然后为它创建了一个模型管理员,并使用自动生成的Django管理表单来创建用户。
所以我在models.py
中有类似的东西class Employee(User):
job = models.CharField(max_length=100)
这在我的admin.py
中class EmployeeAdmin(admin.ModelAdmin):
pass
admin.site.register(Employee, EmployeeAdmin)
现在,Django会自动创建一个表单,用于在Django管理员中添加新员工。但是当使用此表单创建用户时,密码根本不会被散列。因此,出于某种原因,当模型从Django的内置User派生时,Django为密码创建了普通的文本输入字段。我不知道你是否有同样的情况。
不幸的是我找不到一个简单的解决方案来解决这个问题。我也不知道为什么Django没有自动为密码创建正确的表单字段。但是,一种可能性是使用包含密码小部件的自定义表单覆盖自动表单。见https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.formfield_overrides。
答案 1 :(得分:3)
将密码存储为文本而非散列密码的解决方案是使用django.contrib.auth.admin中的UserAdmin而不是ModelAdmin。
from django.contrib.auth.admin import UserAdmin
class EmployeeAdmin(UserAdmin):
pass
admin.site.register(Employee, EmployeeAdmin)
答案 2 :(得分:2)
我遇到了Rubinous回答中显示的相同问题,也可能是您的问题。
从django.contrib.admin.ModelAdmin
而不是django.contrib.auth.admin.UserAdmin
通过这样做,我绕过了必要的用户功能
答案 3 :(得分:0)
Django不会将密码存储为纯文本。它首先散列它们并存储散列。因此,当用户登录时,Django将相同的哈希函数应用于用户输入,然后比较两个哈希 - 来自用户输入和存储在数据库中的内容。
然而,为了使事情更灵活,Django不存储密码哈希值,但它确实存在密码哈希值,但此外,它还存储了生成哈希值的算法。想象一下这种情况 - 您使用散列函数X
来生成密码哈希,但随后您意识到该函数由于某种原因不再是安全的,并且您切换到散列函数Y
。然而,这是一个问题,因为在某一点上,无论谁使用函数X
存储密码哈希,他们将无法再登录。这就是除了哈希值本身之外,Django还存储生成has的方法的原因。这就是PASSWORD_HASHERS
设置的用武之地。事实上Django存储了在db中生成哈希的方法,在读取值时,它并没有真正告诉Django如何执行哈希函数本身。所以PASSWORD_HASHERS
有点像散列Python函数(实际上是一个类,但无论如何......)和存储在db中的值之间的映射器。
回到你的问题。错误消息表示Django不知道用于在您的数据库中存储密码哈希的哈希函数password
,或者至少不在PASSWORD_HASHERS
中。
我可以想到为什么会发生这种情况的几个原因。
确保执行syncdb
,它使用与运行服务器访问管理员时相同的settings.py
文件。可能是使用不同设置的情况。
但是,开发人员通常不会修改PASSWORD_HASHERS
中的settings.py
,只使用默认值。在这种情况下,当您执行syncdb
和运行服务器时,请确保使用与安装版本相同的Django相同的Python。例如,如果您在一个virtualenv中执行syncdb
并在不同的env中运行服务器,则Django版本可能会有所不同,因此它们可能具有PASSWORD_HASHERS
的不同设置,因此您运行的位置{{1}它可能正在使用一个在运行服务器时未定义的散列函数。