【问题标题】:Why isPasswordValid() function always return false?为什么 isPasswordValid() 函数总是返回 false?
【发布时间】:2020-09-05 17:25:29
【问题描述】:

我正在使用 Symfony4 开发一个简单的重置密码系统。

不知道为什么isPasswordValid()总是返回false

我正在使用 Bcrypt 对密码进行哈希处理 这是 Security.yaml 的一些代码:

security:
    encoders:
        App\Entity\User:
            algorithm: bcrypt

我不知道为什么 isPasswordValid() 总是返回 false。 我手动尝试了这个:

$pass="000000000";
dump($encoder->isPasswordValid($user, $pass));
die();

它转储错误..

这是我在控制器上写的函数:

/**
 * @Route("/password", name="change_pass", methods={"GET","POST"})
 * @IsGranted("ROLE_USER")
 */
public function edit(Request $request,UserPasswordEncoderInterface $encoder): Response
{

    $user = $this->getUser();

    $form = $this->createForm(ResetPassType::class, $user);
    $form->handleRequest($request);

    if ($form->isSubmitted() && $form->isValid()) {

        $oldPassword = $request->request->get('reset_pass')['oldPassword'];
        $newPassword = $user->getPassword();

        if ($encoder->isPasswordValid($user, $oldPassword)) {
            $hash = $encoder->encodePassword($user,$newPassword);
            $user->setPassword($hash);
            $this->getDoctrine()->getManager()->flush();
            $this->addFlash('success', 'Your password is succesfully changed');
        }else {
            $this->addFlash('fail', 'old password is wrong');
        }

    }
    $this->getDoctrine()->getManager()->refresh($user);

    return $this->render('consultant/changepass.html.twig', [
        'form' => $form->createView(),
    ]);
}

这里是 ResetPassType 的形式:

   public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
        ->add('oldPassword', PasswordType::class, [
            'mapped' => false,])
        ->add('password',PasswordType::class)
        ;
    }

【问题讨论】:

    标签: php symfony symfony4 change-password


    【解决方案1】:

    简答:您正在使用新密码作为旧密码的哈希值。


    说明:
    我猜您将表单绑定到您的用户类。 表单中的password 字段是映射的,这意味着它会更新用户的password 属性。

    因此,由于该属性应该包含“旧密码”的哈希,但包含您的新密码,因此无法验证。


    解决方案和改进:
    最快的解决方案是 "unmap" password 字段或删除 data_class 表单选项,并替换控制器中的一行:

    // before: $newPassword = $user->getPassword();
    $newPassword = $form->get('password')->getData();
    

    我建议:

    • 将表单取消绑定到您的用户类
    • 为您的oldPassword 字段使用UserPassword 验证约束
    • 使用$form->getData() 获取表单数据,而不是手动访问$request

    【讨论】:

    • 我多次阅读您的答案,但很抱歉我不明白...我不明白我做错了什么?另外,我尝试按照您的建议使用 UserPassword 验证,但即使我输入了正确的密码,它也总是会出现表单错误!它说这是错误的虽然我 100% 确定密码!
    • @MehDi 您将表单绑定到您的用户类,不是吗?我的意思是:在configureOptions() 方法中,您已将data_class 选项设置为您的用户类。由于您的表单有一个新密码的password 字段,因此它会在提交时覆盖您的属性(它将旧密码的哈希替换为新的普通密码)。输入正确的通行证并不重要,将验证所需的哈希替换为新密码,它无法验证。
    • 现在我明白你的意思了。是的,我看到我的错误出现在configureOptions()data_class 现在我使用createFormBuilder() 而不是createForm(ResetPassType) 创建了表单,问题就消失了!我同意使用 UserPassword 验证更好更容易。感谢您提供详细的答案/cmets。
    • @MehDi 很高兴你能理解。顺便说一句,最好将createForm() 与单独的表单类一起使用,而不是直接在控制器中构建表单(您的控制器不必担心表单细节)。
    • 有点离题,但我发现 UserPasswordEncoder 有点难以推理。它隐藏了一些导致问题的原因,例如您的问题。考虑使用 EncoderFactoryInterface 。它可能会使您的代码更易于维护。
    【解决方案2】:

    你会更改你的表单,因为如果你保留字段密码,用户的密码也会被表单更改,所以正确的方法是:

    -在您的表单中:

    public function buildForm(FormBuilderInterface $builder, array $options)
        {
            $builder
            ->add('oldPassword', PasswordType::class, [
                'mapped' => false,])
            ->add('newPassword',PasswordType::class, [
                'mapped' => false,])
            ;
        }
    

    然后在您的控制器中更改获取新密码的方式

    $oldPassword = $request->request->get('reset_pass')['oldPassword'];
    $newPassword = $request->request->get('reset_pass')['newPassword'];
    

    玩得开心:)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-05-20
      • 2011-11-25
      • 1970-01-01
      • 1970-01-01
      • 2017-10-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多