【问题标题】:Why does calling encodePassword() (or hashPasswor()) with identical salts and passwords produces diffent hashes in Symfony?为什么在 Symfony 中使用相同的盐和密码调用 encodePassword()(或 hashPasswor())会产生不同的哈希?
【发布时间】:2019-08-28 14:07:44
【问题描述】:

UserPasswordencoder

public function encodePassword(UserInterface $user, string $plainPassword)
{
    $encoder = $this->encoderFactory->getEncoder($user);
    return $encoder->encodePassword($plainPassword, $user->getSalt());
}

编码器从用户实体获取盐。

我在用户实体中为getSalt() 设置了一个静态变量:

public function getSalt()
{
    return 'my-static-salt';
}

但是当我编码时:

$password  = $encoder->encodePassword($user, "my-password");
$password2 = $encoder->encodePassword($user, "my-password");

$password$password2 彼此不同,就像 encodePassword() 方法使用随机盐一样。

我错过了什么?

【问题讨论】:

    标签: php symfony password-hash


    【解决方案1】:

    Symfony 的注意事项 > 5.4

    从 Symfony 6 开始,这些类和方法的命名更合适,将 Encode 替换为 Hash。并从 Security Core 包移至 Password Hasher 包:

    例如, Symfony\Component\Security\Core\Encoder\EncoderFactory 变为 Symfony\Component\PasswordHasher\Hasher\PasswordHasherFactory,等等。

    但答案的实质是一样的。


    EncoderFactory 默认为您提供NativePasswordEncoder 的实例(除非您安装了 libsodium 库,在这种情况下,它会为您提供SodiumPasswordEncoder)。

    如果您查看NativePasswordEncoder::encodePassword(),您会看到this

    public function encodePassword($raw, $salt)
    {
        if (\strlen($raw) > self::MAX_PASSWORD_LENGTH) {
            throw new BadCredentialsException('Invalid password.');
        }
    
        // Ignore $salt, the auto-generated one is always the best
    
        $encoded = password_hash($raw, $this->algo, $this->options);
    
        if (72 < \strlen($raw) && 0 === strpos($encoded, '$2')) {
            // BCrypt encodes only the first 72 chars
            throw new BadCredentialsException('Invalid password.');
        }
    
        return $encoded;
    }
    

    注意这条评论:

    //忽略$salt,自动生成的总是最好的

    如果你没有将盐字符串传递给password_hash(),它会在你每次调用它时生成自己随机生成的盐,并将盐存储在操作的结果中(以及使用的哈希算法)。

    (同样,在SodiumPasswordEncoder 中,您会看到$salt is not used at all,尽管不存在类似的评论)。

    进一步阅读:

    【讨论】:

    • 感谢您的回答。对我来说,获得相同的密码编码实际上并不重要。问题是,isPasswordValid 返回 false: $encoder->isPasswordValid($user, $plainPassword)
    • 好的,我找到了第二个问题的答案。看来我错误地调用了 $user 。谢谢。
    猜你喜欢
    • 2019-05-08
    • 2011-01-14
    • 1970-01-01
    • 1970-01-01
    • 2017-11-15
    • 2012-08-13
    • 2012-03-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多