Mettre en œuvre le mot de passe de changement dans Symfony2
Quelle est la meilleure façon d'implémenter la fonctionnalité de changement de mot de passe dans Symfony2? Actuellement, 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é.
Remarque:: Je n'utilise pas FOSUserBundle
.
5 réponses
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(),
));
}
}
Vous devez soit créer un autre modèle avec deux champs:
- pour le mot de passe actuel;
- et l'autre pour le nouveau.
ou ajouter une propriété non-persistent à votre modèle d'utilisateur comme le fait le FOSUserBundle (voir plainPassword
propriété).
ainsi, une fois que vous avez vérifié que le mot de passe actuel et le nouveau sont valides, vous encodez le nouveau mot de passe et vous le remplacez par l'ancien.
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',
));
j'utilise une action de mon controller:
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(
));
}
ne pouvez-vous pas obtenir l'ancien mot de passe de L'Utilisateur avant de lier le formulaire?
// in action:
$oldpassword = $user->getPassword();
if ($request->getMethod() == 'POST')
{
$form->bindRequest($request);
if ($form->isValid())
{
// check password here (by hashing new one)