【问题标题】:Implement change password in Symfony2在 Symfony2 中实现更改密码
【发布时间】:2012-02-26 03:18:26
【问题描述】:

在 Symfony2 中实现更改密码功能的最佳方式是什么? 现在我正在使用这个:

$builder->add('password', 'repeated', array(
    'first_name' => 'New password',
    'second_name' => 'Confirm new password',
    'type' => 'password'
));

出于安全原因,它还应包含当前密码检查。

注意:我没有使用FOSUserBundle

【问题讨论】:

    标签: forms security symfony doctrine-orm


    【解决方案1】:

    从 Symfony 2.3 开始,您可以轻松使用 UserPassword 验证约束。

    Acme\UserBundle\Form\Model\ChangePassword.php

    namespace Acme\UserBundle\Form\Model;
    
    use Symfony\Component\Security\Core\Validator\Constraints as SecurityAssert;
    use Symfony\Component\Validator\Constraints as Assert;
    
    class ChangePassword
    {
        /**
         * @SecurityAssert\UserPassword(
         *     message = "Wrong value for your current password"
         * )
         */
         protected $oldPassword;
    
        /**
         * @Assert\Length(
         *     min = 6,
         *     minMessage = "Password should be at least 6 chars long"
         * )
         */
         protected $newPassword;
    }
    

    Acme\UserBundle\Form\ChangePasswordType.php

    namespace Acme\UserBundle\Form;
    
    use Symfony\Component\Form\AbstractType;
    use Symfony\Component\Form\FormBuilderInterface;
    use Symfony\Component\OptionsResolver\OptionsResolverInterface;
    
    class ChangePasswordType extends AbstractType
    {
        public function buildForm(FormBuilderInterface $builder, array $options)
        {
            $builder->add('oldPassword', 'password');
            $builder->add('newPassword', 'repeated', array(
                'type' => 'password',
                'invalid_message' => 'The password fields must match.',
                'required' => true,
                'first_options'  => array('label' => 'Password'),
                'second_options' => array('label' => 'Repeat Password'),
            ));
        }
    
        public function setDefaultOptions(OptionsResolverInterface $resolver)
        {
            $resolver->setDefaults(array(
                'data_class' => 'Acme\UserBundle\Form\Model\ChangePassword',
            ));
        }
    
        public function getName()
        {
            return 'change_passwd';
        }
    }
    

    Acme\UserBundle\Controller\DemoController.php

    namespace Acme\UserBundle\Controller;
    
    use Symfony\Bundle\FrameworkBundle\Controller\Controller;
    use Symfony\Component\HttpFoundation\Request;
    use Acme\UserBundle\Form\ChangePasswordType;
    use Acme\UserBundle\Form\Model\ChangePassword;
    
    class DemoController extends Controller
    {
        public function changePasswdAction(Request $request)
        {
          $changePasswordModel = new ChangePassword();
          $form = $this->createForm(new ChangePasswordType(), $changePasswordModel);
    
          $form->handleRequest($request);
    
          if ($form->isSubmitted() && $form->isValid()) {
              // perform some action,
              // such as encoding with MessageDigestPasswordEncoder and persist
              return $this->redirect($this->generateUrl('change_passwd_success'));
          }
    
          return $this->render('AcmeUserBundle:Demo:changePasswd.html.twig', array(
              'form' => $form->createView(),
          ));      
        }
    }
    

    【讨论】:

    • 不登录也可以修改密码吗?
    • @AjayPatel 不,这是不可能的。 UserPasswordValidator uses security context 当前认证用户
    • 是否可以访问表单域以在树枝中设置样式?因为在 ChangePassword.php 中只有一个“newPassword”字段。
    • @Zwen2012:是的,如指南中所示symfony.com/doc/current/reference/forms/types/repeated.html
    • @jkucharovic 这对我很有效。但是当我的密码是浏览器的“保存密码”时,对于这种形式,“旧密码”是预先填写的,如果密码多次更改,则预先填写的密码是错误的密码。所以我怎样才能让“旧密码”始终为空?试过 'array('always_empty' => false)' 但它没有用。有什么解决办法吗?
    【解决方案2】:

    您必须创建另一个具有两个字段的模型:

    • 一个用于当前密码;
    • 另一个用于新的。

    或者像 FOSUserBundle 那样为您的用户模型添加一个非持久化属性(参见plainPassword 属性)。

    因此,一旦您检查了当前密码和新密码都有效,您就可以对新密码进行编码并用它替换旧密码。

    【讨论】:

      【解决方案3】:

      只需将其添加到您的表单类型中:

      $builder->add('oldPlainPassword', \Symfony\Component\Form\Extension\Core\Type\PasswordType::class, array(
          'constraints' => array(
              new \Symfony\Component\Security\Core\Validator\Constraints\UserPassword(),
          ),
          'mapped' => false,
          'required' => true,
          'label' => 'Current Password',
      ));
      

      【讨论】:

      • 我使用的时候出现这个错误->>> User对象必须实现UserInterface接口。
      【解决方案4】:

      我使用控制器中的操作:

      public function changepasswordAction(Request $request) {
          $session = $request->getSession();
      
          if($request->getMethod() == 'POST') {
              $old_pwd = $request->get('old_password');
              $new_pwd = $request->get('new_password');
              $user = $this->getUser();
              $encoder = $this->container->get('security.encoder_factory')->getEncoder($user);
              $old_pwd_encoded = $encoder->encodePassword($old_pwd, $user->getSalt());
      
              if($user->getPassword() != $old_pwd_encoded) {
                  $session->getFlashBag()->set('error_msg', "Wrong old password!");
              } else {
                  $new_pwd_encoded = $encoder->encodePassword($new_pwd, $user->getSalt());
                  $user->setPassword($new_pwd_encoded);
                  $manager = $this->getDoctrine()->getManager();
                  $manager->persist($user);
      
                  $manager->flush();
                  $session->getFlashBag()->set('success_msg', "Password change successfully!");
              }
              return $this->render('@adminlte/profile/change_password.html.twig');
          }
      
          return $this->render('@adminlte/profile/change_password.html.twig', array(
      
          ));
      }
      

      【讨论】:

        【解决方案5】:

        你不能在绑定表单之前从用户那里得到旧密码吗?

        // in action:
        $oldpassword = $user->getPassword();
        
        if ($request->getMethod() == 'POST') 
                {
                    $form->bindRequest($request);
        
                    if ($form->isValid()) 
                    {
                        // check password here (by hashing new one)
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2023-03-23
          • 1970-01-01
          • 2015-08-21
          • 2023-03-29
          • 2021-09-02
          • 2021-02-09
          • 1970-01-01
          相关资源
          最近更新 更多