如何使用 Symfony 4 中的 fos 用户将用户迁移到新的密码哈希算法?

How to Migrate users to new password hashing algorithms with fos user in Symfony 4?

我有一个带有 fos 用户的旧 Symfony 2 应用程序,其中包含使用 sha512 算法编码的密码。

我希望在将 table 用户迁移到具有 fos 用户 2.1 的新应用程序 symfony 4 之后,当用户使用侦听器登录时能够使用算法 bcrypt 修改密码。

在 Symfony 下可以有多个编码器,但问题是我们不能用不同的算法复制相同的编码器,例如:

    encoders:
        FOS\UserBundle\Model\UserInterface: sha512
        FOS\UserBundle\Model\UserInterface: bcrypt

或使用此代码,我收到此错误消息:

Unrecognized option "FOS\UserBundle\Model\UserInterface" under "security.encoders.old"

    encoders:
        old:
            FOS\UserBundle\Model\UserInterface:
            algorithm: sha512
        new:
            FOS\UserBundle\Model\UserInterface:
            algorithm: bcrypt

更新到已发布的 Symfony 4.4 earlier this week

4.4 支持 Password Migrations

将您的编码器声明为 "auto",这样 Symfony 将始终为新密码选择最好的编码器,并为旧密码选择合适的编码器:

encoders:
        FOS\UserBundle\Model\UserInterface:
            algorithm: auto
            cost: 14

然后让你的 UserRepository 实现 PasswordUpgraderInterface。此接口包含一个方法 upgradePassword(),每当需要将哈希升级到更新的算法时调用该方法。

文档中的示例实现如下:

// ...
use Symfony\Component\Security\Core\User\PasswordUpgraderInterface;

class UserRepository extends EntityRepository implements PasswordUpgraderInterface
{
    // ...

    public function upgradePassword(UserInterface $user, string $newEncodedPassword): void
    {
        // this code is only an example; the exact code will depend on
        // your own application needs
        $user->setPassword($newEncodedPassword);
        $this->getEntityManager()->flush($user);
    }
}

根据您的用例进行调整,当用户登录到您的应用程序时,您将能够透明地将您的密码哈希更新为最新的哈希算法。

由于现代散列算法将散列存储在与散列密码相同的字段上,如果您的旧散列机制依赖于单独的散列字段,您可以在此过程中将其设置为 null,因为它不再需要。

这项新功能的好消息。 所以我迁移到4.4版本。

我更改了 Fos User 的自定义用户提供程序:


use Symfony\Component\Security\Core\User\PasswordUpgraderInterface;

public function upgradePassword(SecurityUserInterface $user, string $newEncodedPassword): void
    {
        // set the new encoded password on the User object
        $user->setPassword($newEncodedPassword);
        //you can set salt to null because the new encoders use algorithms without the salt
        $user->setSalt(null);
        // store the new password
        $this->userManager->updateUser($user);
    }

这很有效!

但是 Fos 用户包有一个问题,当用户修改他的密码时,这会创建一个未使用的新盐。最主要的是它有效。