Для Symfony 2.1 существует встроенное ограничение .
Сначала вы должны создать пользовательское ограничение проверки . Вы можете зарегистрировать валидатор как сервис и добавить в него все, что вам нужно.
Во-вторых, поскольку вы, вероятно, не хотите добавлять поле для текущего пароля в класс User только для того, чтобы привязать к нему ограничение, вы можете использовать то, что называется модель формы . По сути, вы создаете класс в пространстве имен 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 , поэтому я не передаю соль в качестве третьего аргумента методу $encoder->isPasswordValid()
, но я думаю, что вы сможете адаптировать этот пример к вашим потребностям сами.
Кроме того, я использую JMSDiExtraBundle
для упрощения разработки, но вы, конечно, можете использовать классический способ конфигурирования контейнера службы.