php - 在表单类型中使用 Symfony2 UserPassword 验证器

标签 php validation symfony passwords formbuilder

我正在尝试在表单中使用特定的验证器。

该表格供用户重新定义密码,他还必须输入当前密码。 为此,我使用了 symfony 的内置验证器

在我的表单中:

use Symfony\Component\Security\Core\Validator\Constraints\UserPassword;

表单类型如下所示:

 /**
 * @param FormBuilderInterface $builder
 * @param array $options
 */
public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('currentpassword', 'password', array('label'=>'Current password',
            'mapped' => false,
            'constraints' => new UserPassword(array('message' => 'you wot m8?')),
            'required' => true
        ))
        ->add('password', 'repeated', array(
            'first_name' => 'new',
            'second_name' => 'confirm',
            'type' => 'password',
            'required' => true
        ))
    ;
}

我知道在我的 Controller 中我只能获取数据表单、获取当前密码值、调用 security.encoder_factory 等,但验证器看起来很方便。

我的问题是表单总是返回错误(此处:'you wot m8?')就像我输入了错误的当前密码一样。

知道我做错了什么吗?

最佳答案

我知道这个答案晚了几年,但是当我遇到同样的问题时,我想提出我的解决方案:

问题是在我的案例中,我用于 FormMapping 的 $user 实体与来自 security.context 的 User 之间存在连接

请参阅以下内容:(密码更改 - Controller )

    $username = $this->getUser()->getUsername();
    $user = $this->getDoctrine()->getRepository("BlueChordCmsBaseBundle:User")->findOneBy(array("username"=>$username));
    // Equal to $user = $this->getUser();

    $form = $this->createForm(new ChangePasswordType(), $user);
    //ChangePasswordType equals the one 'thesearentthedroids' posted


    $form->handleRequest($request);
    if($request->getMethod() === "POST" && $form->isValid()) {
        $manager = $this->getDoctrine()->getManager();
        $user->setPassword(password_hash($user->getPassword(), PASSWORD_BCRYPT));
        [...]
    }

    return array(...);

isValid() 函数正在触发用户密码约束验证器:

public function validate($password, Constraint $constraint)
{
    if (!$constraint instanceof UserPassword) {
        throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\UserPassword');
    }

    $user = $this->tokenStorage->getToken()->getUser();

    if (!$user instanceof UserInterface) {
        throw new ConstraintDefinitionException('The User object must implement the UserInterface interface.');
    }

    $encoder = $this->encoderFactory->getEncoder($user);

    if (!$encoder->isPasswordValid($user->getPassword(), $password, $user->getSalt())) {
        $this->context->addViolation($constraint->message);
    }
}

感兴趣的行是:if (!$encoder->isPasswordValid($user->getPassword(), $password, $user->getSalt()))

在我的例子中,$user->getPassword() 返回了我刚刚在表单中输入的新密码作为我的新密码。 这就是测试总是失败的原因! 我不明白为什么 tokenStorage 中的用户与我从数据库加载的用户之间存在连接。 感觉两个对象(MyDatabase 一个和 tokenStorage 一个)共享相同的处理器地址并且实际上是相同的...

奇怪!

我的解决方案是将 ChangePasswordType 中的(新)密码字段与 EntityMapping 分离:参见

        ->add('currentpassword', 'password', array('label'=>'Current password', 'mapped' => false, 'constraints' => new UserPassword()))
        ->add('password', 'repeated', array(
            'mapped'          => false,
            'type'            => 'password',
            'invalid_message' => 'The password fields must match.',
            'required'        => true,
            'first_options'   => array('label' => 'Password'),
            'second_options'  => array('label' => 'Repeat Password'),
            ))
        ->add('Send', 'submit')
        ->add('Reset','reset')

感兴趣的行是'mapped' => false,

这样,在表单中输入的新密码将不会自动映射到给定的 $user 实体。相反,您现在需要从 form 中获取它。见

    $form->handleRequest($request);
    if($request->getMethod() === "POST" && $form->isValid()) {
        $data = $form->getData();
        $manager = $this->getDoctrine()->getManager();
        $user->setPassword(password_hash($data->getPassword(), PASSWORD_BCRYPT));
        $manager->persist($user);
        $manager->flush();
    }

解决我无法完全理解的问题的一些方法。如果有人能解释数据库对象和 security.context 对象之间的联系,我将很高兴听到!

关于php - 在表单类型中使用 Symfony2 UserPassword 验证器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22042998/

相关文章:

PHP替换图像src并从包含不同html标签的字符串在图像标签中添加新属性

java - 扫描仪类别验证

java bean 验证 2.0 与 hibernate validator

php - 使 Symfony2 资源与 SSL 一起工作

php - 在 Div 中居中输出文本

php - 自定义 Woocommerce 添加到购物车在 Firefox 中不起作用,但在 Chrome 中不起作用

javascript - 将 PHP 数组转换为 JS 变量

xml - Powershell XML 验证

php - Doctrine 2 在更新时获得匹配的行数而不是受影响

sqlite - 存储我的服务 sqlite 数据库文件的最佳位置?