web-dev-qa-db-fra.com

Implémenter le mot de passe de changement dans symfony2

Quelle est la meilleure façon de mettre en œuvre la fonctionnalité de changement de mot de passe dans Symfony2? En ce moment, j'utilise ceci:

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

Il devrait également contenir la vérification du mot de passe actuel pour des raisons de sécurité.

NOTE: Je n'utilise pas FOSUserBundle.

24
kuboslav

Depuis Symfony 2.3, vous pouvez facilement utiliser UserPassword contrainte de validation.

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 by 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(),
      ));      
    }
}
51
jkucharovic

Vous devez soit créer un autre modèle avec deux champs:

  • un pour le mot de passe actuel;
  • et l'autre pour le nouveau.

Ou ajoutez une propriété non persistée à votre modèle utilisateur tel que la FosuserBundle (voir la propriété plainPassword).

Donc, une fois que vous avez vérifié que le mot de passe actuel et nouveau est valide, vous encodez le nouveau mot de passe et remplacez l'ancien avec celui-ci.

8
Herzult

Il suffit d'ajouter ceci à votre type de formulaire:

$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',
));
5
Taylan

J'utilise une action de mon contrôleur:

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(

    ));
}
4
Le Hoai Duc

Vous ne pouvez pas obtenir de mot de passe ancien de l'utilisateur avant la liaison?

// in action:
$oldpassword = $user->getPassword();

if ($request->getMethod() == 'POST') 
        {
            $form->bindRequest($request);

            if ($form->isValid()) 
            {
                // check password here (by hashing new one)
1
jpass