为什么使用相同的盐和密码调用 encodePassword()(或 hashPasswor())会在 Symfony 中产生不同的哈希值?
Why does calling encodePassword() (or hashPasswor()) with identical salts and passwords produces diffent hashes in Symfony?
在UserPassword
encoder,
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()
方法使用了随机盐。
我错过了什么?
Symfony > 5.4 的注意事项
从 Symfony 6 开始,这些 类 和方法的命名更恰当,用 Hash
替换了 Encode
。并从 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, '')) {
// BCrypt encodes only the first 72 chars
throw new BadCredentialsException('Invalid password.');
}
return $encoded;
}
注意这条评论:
// Ignore $salt, the auto-generated one is always the best
如果您不将盐字符串传递给 password_hash()
,它会在您每次调用它时生成自己随机生成的盐,并将盐存储在操作结果中(以及使用的哈希算法).
(同样,在 SodiumPasswordEncoder
中你会看到 $salt
is not used at all,尽管不存在类似的评论)。
进一步阅读:
在UserPassword
encoder,
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()
方法使用了随机盐。
我错过了什么?
Symfony > 5.4 的注意事项
从 Symfony 6 开始,这些 类 和方法的命名更恰当,用 Hash
替换了 Encode
。并从 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, '')) {
// BCrypt encodes only the first 72 chars
throw new BadCredentialsException('Invalid password.');
}
return $encoded;
}
注意这条评论:
// Ignore $salt, the auto-generated one is always the best
如果您不将盐字符串传递给 password_hash()
,它会在您每次调用它时生成自己随机生成的盐,并将盐存储在操作结果中(以及使用的哈希算法).
(同样,在 SodiumPasswordEncoder
中你会看到 $salt
is not used at all,尽管不存在类似的评论)。
进一步阅读: