UserChecker - использовать менеджер сущностей
Мой сайт работает под управлением Symfony 3.4, и я создал собственную систему пользователей. Моя сущность User содержит поле Datetime 'lastLogin', и я не могу найти решение для его обновления каждый раз, когда пользователь входит в систему.
Я создал пользовательский UserChecker, а затем попытался обновить поле в нем:
<?php
namespace CoreBundle\Security;
use CoreBundle\Entity\User as AppUser;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\User\UserCheckerInterface;
use Symfony\Component\Security\Core\User\UserInterface;
class UserChecker implements UserCheckerInterface
{
public function checkPreAuth(UserInterface $user)
{
if (!$user instanceof AppUser) {
return;
}
if ( $user->getDeleted() || !$user->getEnabled() )
{
throw new AuthenticationException();
}
else
{
// BELOW IS WHAT I TRY, BUT FAIL.
$entityManager = $this->get('doctrine')->getManager();
$user->setLastLogin(new \DateTime());
$entityManager->persist($user);
$entityManager->flush();
}
}
public function checkPostAuth(UserInterface $user)
{
if (!$user instanceof AppUser) {
return;
}
}
}
Но это не работает. Может быть, я не могу использовать менеджер сущностей доктрины в этом файле?
Если я использую $this->get('doctrine')->getManager();
Я получил:
Неустранимая ошибка: вызов неопределенного метода CoreBundle\Security\UserChecker::get()
1 ответ
Не знаю, почему @doncallisto удалил свой пост. Это было (ИМХО) правильное.
Взгляните на http://symfony.com/doc/current/components/security/authentication.html
Итак, у вас есть несколько вариантов.
SecurityEvents::INTERACTIVE_LOGIN
- срабатывает каждый раз, когда пользователь заполняет форму входа и отправляет учетные данные. Будет работать, но выне будете получать обновления last_login, если у вас естьremember_me
печенье или подобноеAuthenticationEvents::AUTHENTICATION_SUCCESS
- срабатывает каждый раз(каждый запрос), когда аутентификация прошла успешно. Это означает, что вашlast_login
будет обновляться каждый раз при каждом запросе, если пользователь не вышел из системы
так что вам нужен EventSubscriber. Посмотрите на эту статью. https://thisdata.com/blog/subscribing-to-symfonys-security-events/
Возможно, вам понадобится упрощенная версия.
public static function getSubscribedEvents()
{
return array(
// AuthenticationEvents::AUTHENTICATION_FAILURE => 'onAuthenticationFailure', // no need for this at that moment
SecurityEvents::INTERACTIVE_LOGIN => 'onSecurityInteractiveLogin', // this ist what you want
);
}
а затем onSecurityInteractiveLogin
сам метод.
public function onSecurityInteractiveLogin( InteractiveLoginEvent $event )
{
$user = $this->tokenStorage->getToken()->getUser();
if( $user instanceof User )
{
$user->setLastLogin( new \DateTime() );
$this->entityManager->flush();
}
}
PS FosUserBundle использует interactive_login и пользовательское событие для установки last_login при просмотре сущности: https://github.com/FriendsOfSymfony/FOSUserBundle/blob/master/EventListener/LastLoginListener.php
Друг, вы можете использовать это, чтобы ввести entityManager с помощью конструктора
use Doctrine\ORM\EntityManagerInterface;
public function __construct(EntityManagerInterface $userManager){
$this->userManager = $userManager;
}
И в checkPreAuth вы называете это
public function checkPreAuth(UserInterface $user){
if (!$user instanceof AppUser) {
return;
}
if ( $user->getDeleted() || !$user->getEnabled() ){
throw new AuthenticationException();
}else{
// BELOW IS WHAT I TRY, BUT FAIL.
$user->setLastLogin(new \DateTime());
$this->userManager->persist($user);
$this->userManager->flush();
}
}