Проверка пароля в Symfony2
Я пытаюсь собрать функцию смены пароля в Symfony2. У меня есть поле" текущий пароль", поле" новый пароль "и поле" подтвердить новый пароль", и часть, на которой я сейчас фокусируюсь, проверяет поле" текущий пароль".
(кстати, теперь я понимаю, что такие вещи, как что бы позаботиться о многих из этих вещей для меня, но я уже построил свою систему аутентификации на основе официальной документации по 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);
}
}
Как вы можете видеть в моих комментариях, есть по крайней мере несколько причин, по которым приведенный выше код не работает. Я бы просто разместил конкретные вопросы об этих конкретных проблемах, но, возможно, я лаю не на то дерево. Вот почему я задаю общий вопрос.
Итак, как я могу проверить пароль пользователя?
4 ответов
здесь встроенные ограничения для этого с Symfony 2.1.
во-первых, вы должны создать пользовательское ограничение проверки. Вы можете зарегистрировать валидатор как услугу и ввести в него все, что вам нужно.
во-вторых, поскольку вы, вероятно, не хотите добавлять поле для текущего пароля в класс пользователя, чтобы просто придерживаться ограничения, вы можете использовать то, что называется модель форма. По сути, вы создаете класс 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, поэтому я не передаю соль в качестве третьего аргумента the $encoder->isPasswordValid()
метод, но я думаю, что вы сможете адаптировать этот пример к своим потребностям самостоятельно.
кроме того, я использую JMSDiExtraBundle
упростить развитие, но вы можете конечно использовать классический путь конфигурации контейнера обслуживания.
в 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
FOSUserBundle
использует ModelManager
класс, который отделен от базы модель. Вы можете проверить их реализация.
Я закончил тем, что разрубил гордиев узел. Я обошел все формы Symfony и сделал всю логику в контроллере.