passwordEncoder 为非身份验证目的生成的哈希在验证时失败
passwordEncoder generated hash for non-authentication purpose fails on verification
为了让用户在我的系统上注册,我发送了一封带有生成的 link 的确认邮件。单击时系统应将活动 属性 设置为 true。
为了创建确认 link,我生成了一个 md5 散列 random_byte 值。该值是我发送给用户的 link 的一部分。该值使用 passwordEncoder 进行哈希处理并存储在我的数据库中。
当用户单击 link 时,系统会根据我的数据库中的哈希检查该值,并且应该 return 为真,以完全激活用户。由于某种原因验证失败。
我检查过,register() 中生成的 $identifier 值是发送给用户的值。他们匹配。所以没有错。
起初我只想用password_verify(),但也没成功。
我根本不知道为什么它不起作用。我最后的猜测是,有一些我不知道的 Symfony 黑魔法在进行。
public function register(EntityManagerInterface $entityManager, Request $request, UserPasswordEncoderInterface $passwordEncoder, MailerInterface $mailer)
{
// Register-Form
$form = $this->createForm(RegisterFormType::class);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
/** @var User $user */
$user = $form->getData();
$user->setPassword($passwordEncoder->encodePassword(
$user,
$form['plainPassword']->getData()
));
// create activation hash
$identifier = md5(random_bytes(16));
$user->setActiveHash(
$passwordEncoder->encodePassword(
$user,
$identifier
)
);
// send activation mail with activation hash
$message = (new TemplatedEmail())
->subject('...')
->from('...')
->to($user->getEmail())
->textTemplate('emails/registration.txt.twig')
->context([
'mail' => $user->getEmail(),
'identifier' => $identifier,
])
;
$mailer->send($message);
// persist & flush
$entityManager->persist($user);
$entityManager->flush();
$this->addFlash('success', '...');
//return $this->redirectToRoute('login');
return $this->render('home/index.html.twig');
}
return $this->render('security/register.html.twig', [
'registerForm' => $form->createView()
]);
}
/**
* @Route("/confirm/{email}/{identifier}", name="register.confirm")
*/
public function confirm($email, $identifier, EntityManagerInterface $entityManager, UserPasswordEncoderInterface $passwordEncoder)
{
$user = $entityManager->getRepository(User::class)->findOneBy([
'email' => $email,
'active' => false
]);
if (!$user) {
// fail no user with email
die('no such user');
}
if( !$passwordEncoder->isPasswordValid($user, $identifier) ){
// Hash verification failed
die('hash failed');
}
$user->setActive(true);
$entityManager->persist($user);
$entityManager->flush();
$this->addFlash('success', '...');
return $this->redirectToRoute('login');
}
编辑:
我尝试用 password_hash('a_string', PASSWORD_ARGON2ID)
手动散列字符串,它抛出一个异常 PASSWORD_ARGON2ID 是一个未定义的常量。 PASSWORD_ARGON2I 有效。 Symfony 以某种方式使用 Argon2ID 作为我的密码字符串,而通过 encodePassword() 生成的 activeHash 字符串以“$argon2id...”开头,这怎么可能?
好的。所以我在本地通过 MAMP 是 运行 PHP 7.2。正如 msg 在评论中提到的(在删除之前),Argon2ID 哈希可能是由 Sodium 提供的。另一方面,7.2 password_verify() 无法验证 argon2id 哈希。
已升级到 PHP 7.3.7,没有问题了。
为了让用户在我的系统上注册,我发送了一封带有生成的 link 的确认邮件。单击时系统应将活动 属性 设置为 true。
为了创建确认 link,我生成了一个 md5 散列 random_byte 值。该值是我发送给用户的 link 的一部分。该值使用 passwordEncoder 进行哈希处理并存储在我的数据库中。
当用户单击 link 时,系统会根据我的数据库中的哈希检查该值,并且应该 return 为真,以完全激活用户。由于某种原因验证失败。
我检查过,register() 中生成的 $identifier 值是发送给用户的值。他们匹配。所以没有错。
起初我只想用password_verify(),但也没成功。
我根本不知道为什么它不起作用。我最后的猜测是,有一些我不知道的 Symfony 黑魔法在进行。
public function register(EntityManagerInterface $entityManager, Request $request, UserPasswordEncoderInterface $passwordEncoder, MailerInterface $mailer)
{
// Register-Form
$form = $this->createForm(RegisterFormType::class);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
/** @var User $user */
$user = $form->getData();
$user->setPassword($passwordEncoder->encodePassword(
$user,
$form['plainPassword']->getData()
));
// create activation hash
$identifier = md5(random_bytes(16));
$user->setActiveHash(
$passwordEncoder->encodePassword(
$user,
$identifier
)
);
// send activation mail with activation hash
$message = (new TemplatedEmail())
->subject('...')
->from('...')
->to($user->getEmail())
->textTemplate('emails/registration.txt.twig')
->context([
'mail' => $user->getEmail(),
'identifier' => $identifier,
])
;
$mailer->send($message);
// persist & flush
$entityManager->persist($user);
$entityManager->flush();
$this->addFlash('success', '...');
//return $this->redirectToRoute('login');
return $this->render('home/index.html.twig');
}
return $this->render('security/register.html.twig', [
'registerForm' => $form->createView()
]);
}
/**
* @Route("/confirm/{email}/{identifier}", name="register.confirm")
*/
public function confirm($email, $identifier, EntityManagerInterface $entityManager, UserPasswordEncoderInterface $passwordEncoder)
{
$user = $entityManager->getRepository(User::class)->findOneBy([
'email' => $email,
'active' => false
]);
if (!$user) {
// fail no user with email
die('no such user');
}
if( !$passwordEncoder->isPasswordValid($user, $identifier) ){
// Hash verification failed
die('hash failed');
}
$user->setActive(true);
$entityManager->persist($user);
$entityManager->flush();
$this->addFlash('success', '...');
return $this->redirectToRoute('login');
}
编辑:
我尝试用 password_hash('a_string', PASSWORD_ARGON2ID)
手动散列字符串,它抛出一个异常 PASSWORD_ARGON2ID 是一个未定义的常量。 PASSWORD_ARGON2I 有效。 Symfony 以某种方式使用 Argon2ID 作为我的密码字符串,而通过 encodePassword() 生成的 activeHash 字符串以“$argon2id...”开头,这怎么可能?
好的。所以我在本地通过 MAMP 是 运行 PHP 7.2。正如 msg 在评论中提到的(在删除之前),Argon2ID 哈希可能是由 Sodium 提供的。另一方面,7.2 password_verify() 无法验证 argon2id 哈希。
已升级到 PHP 7.3.7,没有问题了。