2012-02-03 37 views
19

¿Cuál es la mejor manera de implementar la funcionalidad de cambio de contraseña en Symfony2? Ahora estoy usando esto:Implementar cambio de contraseña en Symfony2

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

También debe contait comprobación de la contraseña actual por razones de seguridad.

Nota: No estoy usando FOSUserBundle.

Respuesta

43

Desde Symfony 2.3 puede utilizar simplemente UserPassword restricción de validación.

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 \ Controlador \ 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(), 
    ));  
    } 
} 
+0

es posible cambiar la contraseña sin acceso? –

+0

@AjayPatel no, no es posible. 'UserPasswordValidator' [usa el contexto de seguridad] (https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Security/Core/Validator/Constraints/UserPasswordValidator.php#L37) del usuario autenticado actual – jkucharovic

+0

está bien la solución no hay problema. –

7

Tienes que o bien crear otro modelo con dos campos:

  • uno para la contraseña actual;
  • y el otro para el nuevo.

O agregue una propiedad no persistente a su modelo de usuario como lo hace FOSUserBundle (vea la propiedad plainPassword).

Una vez que haya comprobado que la contraseña actual y la nueva son válidas, codifique la nueva contraseña y reemplace la anterior.

1

¿No puede obtener una contraseña anterior del usuario antes de vincular el formulario?

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

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

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

utilizo una acción de mi controlador:

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(

    )); 
} 
3

sólo Agregar a su tipo de formulario:

$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', 
)); 
Cuestiones relacionadas