我在使用syncdb
命令时创建了一个用户,它可以完美登录。但是当我从 django admin 创建用户时,它已成功创建,但在登录时会导致错误。我收到错误:
Unknown password hashing algorithm 'password'. Did you specify it in the PASSWORD_HASHERS setting?
有什么问题?如何解决它,以便在管理员中保存用户时自动加密密码?
将密码存储为文本而不是散列密码的解决方案是使用 django.contrib.auth.admin 中的 UserAdmin 而不是 ModelAdmin。
from django.contrib.auth.admin import UserAdmin
class EmployeeAdmin(UserAdmin):
pass
admin.site.register(Employee, EmployeeAdmin)
我在子类化 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 admin 中添加新员工。但是当这个表单用于创建用户时,密码根本不会被散列。所以出于某种原因,当模型派生自 Django 的内置用户时,Django 会为密码创建普通的文本输入字段。不知道你有没有同样的情况。
不幸的是,我找不到一个简单的解决方案来解决这个问题。我也不知道为什么 Django 没有自动为密码创建正确的表单字段。然而,一种可能性是使用包含密码小部件的自定义表单覆盖自动表单。请参阅https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.formfield_overrides。
我遇到了 Rubinous 答案中显示的相同问题,也可能是您的问题。
django.contrib.admin.ModelAdmin
从而不是继承我的用户模型时发生了问题django.contrib.auth.admin.UserAdmin
通过这样做,我绕过了必要的用户功能
Django 不将密码存储为纯文本。它首先对它们进行散列,然后它们存储散列。因此,当用户登录时,Django 将相同的哈希函数应用于用户输入,然后比较两个哈希值 - 来自用户输入和存储在数据库中的内容。
然而,为了使事情更灵活,Django 不存储密码哈希,它确实如此,但此外,它还存储生成哈希的算法。想象一下这种情况 - 您使用散列函数X
生成密码散列,但随后您意识到该函数由于某种原因不再安全并且您切换到散列函数Y
。然而,这是一个问题,因为此时,无论谁的密码哈希是使用 function 存储的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。例如,如果您syncdb
在一个 virtualenv 中执行并在不同的 env 中运行服务器,那么 Django 版本可能会有所不同,因此它们可能具有不同的设置PASSWORD_HASHERS
,因此您运行syncdb
的位置可能会使用未定义的哈希函数运行服务器。