Как использовать фабрику кодировщиков в Symfony 2 внутри установщика моделей?
Этот вопрос о Symfony 2.1
Как я могу кодировать пароль пользователя с помощью:
$factory = $this->get('security.encoder_factory');
$user = new Acme\UserBundle\Entity\User();
$encoder = $factory->getEncoder($user);
$password = $encoder->encodePassword('ryanpass', $user->getSalt());
$user->setPassword($password);
И базовый конфиг:
# app/config/security.yml
security:
# ...
encoders:
Acme\UserBundle\Entity\User: sha512
Внутри сеттера модели:
class User implements UserInterface, \Serializable
{
public function setPassword($password)
{
$this->password = $password;
}
}
Я считаю, что процесс шифрования пароля должен иметь дело с моделью. Как я могу использовать стандартный завод по производству энкодеров внутри модели?
2 ответа
Сущность содержит данные, а не обрабатывает их. Если вы хотите изменить данные сущности, вы можете создать прослушиватель событий и делать что-то перед сохранением. Проверьте, как зарегистрировать слушателей событий и подписчиков из официальной документации.
Вы также можете взглянуть на FosUserBundle и его управление пользователями.
Итак, основная идея состоит в том, чтобы передать простой пароль из формы в пользовательский объект и зашифровать его перед сохранением с помощью прослушивателя событий.
Хотя я согласен с @Vadim в том, что вы не должны передавать бизнес-логику в свою модель, я бы с осторожностью отложил хеширование открытого текста до prePersist
событие, например, если вы не позвоните persist
а также flush
сразу после setPassword
, getPassword
Тем временем call будет возвращать текстовую строку, если вы не сохранили ее в отдельном поле, что может иметь серьезные последствия. В идеале открытый текстовый пароль должен существовать как можно более короткое время в течение жизненного цикла приложения.
Я рекомендую использовать сервисный уровень, в котором "Диспетчер пользователей" предоставляет интерфейс для выполнения общих задач, поэтому вам не нужно даже временно загрязнять свой пароль:
class UserManager
{
// ...
public function __construct(EncoderFactoryInterface $encoderFactory)
{
// $encoderFactory is injected by the DIC as requested by your service configuration
// ...
}
public function setUserPassword(UserInterface $user, $plaintextPassword)
{
$hash = $this->encoderFactory->getEncoder($user)->encodePassword($plaintextPassword, null);
$user->setPassword($hash);
}
// ...
}
В вашем контроллере для отправки регистрационной формы, например:
public function userRegistrationAction()
{
// ...
if ($form->isValid()) {
$user = new User();
// ...
$this->get('my.bundle.user_manager')->setUserPassword($user, $form->get('password')->getData());
// ...
}
}