у меня есть User
сущность, которая имеет логический столбец isActivated
, В зависимости от значения столбца для каждого пользователя, он может или не может войти в систему (то есть он не активировал свою учетную запись, поэтому нет входа). Я добился этого, назначив simple_form.authenticator
в брандмауэре, который проверяет каждый логин.
Я пытаюсь выяснить, как заставить пользователя выйти из системы, пока он еще в системе.
Рассмотрим следующий сценарий:
К сожалению, шаг № 3 не происходит. Причина может заключаться в том, что пользователь уже получил токен и считается «переадресованным» Symfony 2.5
брандмауэр (вероятно, токен кэшируется в контексте безопасности?).
Мне интересно, что было бы лучшим способом преодолеть эту проблему? Должен ли я написать слушатель события ядра или, возможно, Пользовательский провайдер?
Вы можете прекратить сеанс пользователя с помощью следующих двух строк (если у вас есть доступ к контейнеру, в противном случае вы должны ввести security.context
а также session
):
$container->get('security.context')->setToken(null);
$container->get('session')->invalidate();
После этого пользователь должен выйти из системы.
Если вы ранее загружали пользовательский объект, вы можете также сбросить его.
Хотя @lxg ответил на мой вопрос, я решил расширить его ответ, чтобы другие люди с такой же проблемой лучше понимали, как решить эту проблему.
Создать прослушиватель событий
namespace Acme\MyBundle\Events;
use Acme\MyBundle\Entity\User;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException;
use Symfony\Component\Security\Core\SecurityContext;
class RequestEvent {
/**
* @var \Symfony\Component\Security\Core\SecurityContext
*/
private $securityContext;
public function __construct(SecurityContext $context){
$this->securityContext = $context;
}
public function onKernelRequest(GetResponseEvent $event)
{
// not sure if this is actually needed?
if (!$event->isMasterRequest()) {
// don't do anything if it's not the master request
return;
}
// try to get security context and catch the exception in case no firewall was configured (i.e. for the dev tool bar)
try{
// trigger only for logged in users
if($this->securityContext->isGranted('IS_AUTHENTICATED_FULLY')){
$token = $this->securityContext->getToken();
/**
* @var User $user
*/
$user = $token->getUser();
if($user != null && !$user->isActive()){
$this->securityContext->setToken(null);
}
}
} catch(AuthenticationCredentialsNotFoundException $e){
// don't do anything here... or do whatever you want.
}
}
}
?>
Теперь в вашем service.yml
Добавь это:
services:
kernel.listener.request_listener:
class: Acme\MyBundle\Events\RequestEvent
arguments: [ @security.context ]
tags:
- { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }
И как только пользователь будет деактивирован, он будет принудительно перенаправлен на страницу входа в систему вашего брандмауэра. Надеюсь, это кому-нибудь поможет.