Django 从使用 password_hash() 的 PHP 站点导入现有的 Ppasswords

Posted

技术标签:

【中文标题】Django 从使用 password_hash() 的 PHP 站点导入现有的 Ppasswords【英文标题】:Django import existing Ppasswords from PHP site that used password_hash() 【发布时间】:2022-01-22 13:19:51 【问题描述】:

我需要将用户列表和散列密码从使用 password_hash() 的旧 php 站点导入到新的 django 站点。存储的密码如下所示:$2y$10$ZnxKDPbqOfACnGmQeN76o.UtdwWBFBCCLTiGnvCSvl/zqIBeVxhai

我在尝试查找时在这里找到了Django password hasher using php format of function password_hash(),我认为这将有助于下一步。

但目前我无法设置能够正确恢复旧密码的导入过程。当我在导入过程中尝试手动创建用户时,它拒绝输入“无效密码格式或未知散列算法”的密码。当我在导入运行后查看用户时。我认为我完全错误地处理了这个问题,这是我创建用户的示例 sn-p。

usertest = User(username='testguy',email='testguy@test.com',password='$2y$10$ZnxKDPbqOfACnGmQeN76o.UtdwWBFBCCLTiGnvCSvl/zqIBeVxhai')

这导致没有密码被存储。使用 create_user 函数会导致创建用户,但使用哈希密码输出作为他们的密码: User.objects.create_user(username='testguy',email='testguy@test.com',password='$2y$10$ZnxKDPbqOfACnGmQeN76o.UtdwWBFBCCLTiGnvCSvl/zqIBeVxhai')

如何才能将这些密码正确存储在新数据库中,以便进行下一步实际检查这些密码?

【问题讨论】:

魔鬼的拥护者。您能否拥有一个非常轻量级的 PHP 脚本,可以在接下来的 6 或 12 个月内使用?或者您的团队可以接受多长时间?让该代码运行非常简单的password_verify 函数,然后在本地重新散列。在这种情况下,你会得到更少的边缘情况,而且更容易证明。你甚至可以把它包装成一个独立的 phar 所以你的意思是当有人登录时,让它检查那个 PHP 脚本,然后如果它正确,重新散列它并将它正常存储在新位置?这可能是可行的,虽然哈哈,但这样做感觉很恶心。我想以一种更“干净”的方式来做这件事,这样我们就不必挂出一个 PHP 脚本,但如果我没有时间/耐心,可以尝试一下。 我过去曾构建过类似的系统(我就是从.Net 到 PHP),虽然感觉很奇怪,但几乎可以保证它可以工作。也就是说,虽然 Python 路径在这里可能没有最好的答案,但有一个 JS version 可以用 Python 重写。 好的,实际上我最终得到了一个您帮助我想到的更简单的解决方案。我刚刚在我的用户数据库中设置了一个新字段来存储旧密码并将导入的散列密码存储在那里。然后在用户登录时,如果他们输入了错误的密码,它会使用 bcrypt 来检查我带来的旧密码,如果匹配,则使用 django 的正常密码设置功能将其设置为输入的内容,我们就可以开始了。感谢您让我走上正确的道路! 【参考方案1】:

我设法找到了一个适合我的解决方法,它并不能完全按照我最初的意图做,但效果很好。对于任何可能希望在这里做类似事情的人来说,这就是我最终要做的事情。

不要将其导入实际的 Django Auth User 密码字段,而是向您的用户添加一个新的 old_password 字段并将旧的散列密码导入其中。

然后编辑您的身份验证函数(可能在 backends.py 中),如果登录时密码检查失败,则使用 bcrypt 检查 old_password 字段:

            if user.check_password(password):
                return user
            else: #didnt match check if its an old user
                if user.old_password != "":
                    if bcrypt.checkpw(bytes(password, 'utf-8'), bytes(user.old_password, 'utf-8')):
                        user.set_password(password)
                        user.save()
                        return user

【讨论】:

以上是关于Django 从使用 password_hash() 的 PHP 站点导入现有的 Ppasswords的主要内容,如果未能解决你的问题,请参考以下文章

使用password_hash密码默认注册登录

如何使用 PHP 的 password_hash 来散列和验证密码

如何使用 PHP 的 password_hash 来散列和验证密码

使用password_hash函数时的密码恢复[重复]

即使安装了passlib,Ansible password_hash也不会使用bcrypt

调用未定义的函数 password_hash() [关闭]