2012-04-01 2 views
9

Я пытаюсь создать функцию изменения пароля в Symfony2. У меня есть поле «текущий пароль», поле «новый пароль» и поле «подтвердить новый пароль», а часть, на которой я сейчас сосредоточен, проверяет поле «текущий пароль».Проверка пароля в Symfony2

(Кстати, теперь я понимаю, что существуют такие вещи, как FOSUserBundle, которые позаботятся о многом для меня, но я уже построил свою систему аутентификации на основе официальной документации Symfony, и у меня нет время прямо сейчас, чтобы переделать все мой код аутентификации)

что я воображал/надеюсь, что я могу сделать, это создать обратный вызов проверки, что говорит что-то вроде этого:.

// Entity/User.php 

public function currentPasswordIsValid(ExecutionContext $context) 
{ 
    $currentPassword = $whatever; // whatever the user submitted as their current password 
    $factory = $this->get('security.encoder_factory'); // Getting the factory this way doesn't work in this context. 
    $encoder = $factory->getEncoder($this); 
    $encryptedCurrentPassword = $encoder->encodePassword($this->getPassword(), $this->getSalt()); 

    if ($encyptedCurrentPassword != $this->getPassword() { 
    $context->addViolation('Current password is not valid', array(), null); 
    } 
} 

Как вы можете видеть в моих комментариях , есть по крайней мере несколько причин, почему приведенный выше код не работает. Я бы просто задал конкретные вопросы по этим конкретным вопросам, но, может быть, я вообще лаю по неправильному дереву. Вот почему я задаю общий вопрос.

Итак, как я могу проверить пароль пользователя?

ответ

10

Для этого есть built-in constraint, так как Symfony 2.1.


Во-первых, вы должны создать custom validation constraint. Вы можете зарегистрировать валидатор как услугу и ввести все, что вам нужно.

Во-вторых, поскольку вы, вероятно, не хотите добавлять поле для текущего пароля к классу User, просто привязав к нему ограничение, вы можете использовать то, что называется form model. По существу, вы создаете класс в пространстве имен Form\Model, который содержит текущее поле пароля и ссылку на объект пользователя. Тогда вы можете привязать свое пользовательское ограничение к этому полю пароля. Затем вы создаете тип формы изменения пароля для этой модели формы.

Вот пример ограничения одного из моих проектов:

<?php 
namespace Vendor\Bundle\AppBundle\Validator\Constraints\User; 

use Symfony\Component\Validator\Constraint; 

/** 
* @Annotation 
*/ 
class CurrentPassword extends Constraint 
{ 
    public $message = "Your current password is not valid"; 

    /** 
    * @return string 
    */ 
    public function validatedBy() 
    { 
     return 'user.validator.current_password'; 
    } 
} 

И его валидатора:

<?php 
namespace Vendor\Bundle\AppBundle\Validator\Constraints\User; 

use Symfony\Component\Validator\ConstraintValidator; 
use Symfony\Component\Validator\Constraint; 
use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface; 
use Symfony\Component\Security\Core\SecurityContextInterface; 
use JMS\DiExtraBundle\Annotation\Validator; 
use JMS\DiExtraBundle\Annotation\InjectParams; 
use JMS\DiExtraBundle\Annotation\Inject; 

/** 
* @Validator("user.validator.current_password") 
*/ 
class CurrentPasswordValidator extends ConstraintValidator 
{ 
    /** 
    * @var EncoderFactoryInterface 
    */ 
    private $encoderFactory; 

    /** 
    * @var SecurityContextInterface 
    */ 
    private $securityContext; 

    /** 
    * @InjectParams({ 
    *  "encoderFactory" = @Inject("security.encoder_factory"), 
    *  "securityContext" = @Inject("security.context") 
    * }) 
    * 
    * @param EncoderFactoryInterface $encoderFactory 
    * @param SecurityContextInterface $securityContext 
    */ 
    public function __construct(EncoderFactoryInterface $encoderFactory, 
           SecurityContextInterface $securityContext) 
    { 
     $this->encoderFactory = $encoderFactory; 
     $this->securityContext = $securityContext; 
    } 

    /** 
    * @param string  $currentPassword 
    * @param Constraint $constraint 
    * @return boolean 
    */ 
    public function isValid($currentPassword, Constraint $constraint) 
    { 
     $currentUser = $this->securityContext->getToken()->getUser(); 
     $encoder = $this->encoderFactory->getEncoder($currentUser); 
     $isValid = $encoder->isPasswordValid(
      $currentUser->getPassword(), $currentPassword, null 
     ); 

     if (!$isValid) { 
      $this->setMessage($constraint->message); 
      return false; 
     } 

     return true; 
    } 
} 

Я использую мой Blofwish password encoder bundle, так что я не передать соль в качестве третьего аргумента к методу $encoder->isPasswordValid(), но я думаю, что вы сможете самостоятельно адаптировать этот пример к вашим потребностям.

Кроме того, я использую JMSDiExtraBundle для упрощения разработки, но вы можете, конечно, использовать классический способ конфигурирования контейнерного контейнера.

+0

Хорошо, спасибо. Но как насчет фактической части проверки пароля? Это то, о чем я спрашивал. Я уже знаю, как создать пользовательский валидатор и как создать поля формы. –

+0

Добавлен пример. –

+0

Удивительный, спасибо. Я попробую. –

0

FOSUserBundle использует класс ModelManager, который отделен от основания Model. Вы можете проверить их implementation.

-3

Я закончил тем, что разрезал гордиев узел. Я обошел все элементы формы Symfony и выполнил всю логику контроллера.

+1

Эй, вы должны попробовать еще раз с новым ограничением проверки UserPassword. – Acyra

6

В Symfony 2.1 вы можете использовать встроенный валидатор: http://symfony.com/doc/master/reference/constraints/UserPassword.html

Так, например, в вашей форме строитель:

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

// mapped=>false (new in 2.1) is to let the builder know this is not an entity field 
->add('currentpassword', 'password', array('label'=>'Current password', 'mapped' => false, 'constraints' => new UserPassword())) 

Видимо есть ошибка прямо сейчас с этим валидатор так, возможно, и мог бы теперь работать https://github.com/symfony/symfony/issues/5460

+1

небольшое примечание, есть опечатка, это должно быть 'Symfony \ Component \ Security \ Core \ Validator \ Constraints \ UserPassword' (' '' отсутствует в Contraints) – loostro

Смежные вопросы