Как можно принудительно выйти из системы в Symfony?

у меня есть User сущность, которая имеет логический столбец isActivated, В зависимости от значения столбца для каждого пользователя, он может или не может войти в систему (то есть он не активировал свою учетную запись, поэтому нет входа). Я добился этого, назначив simple_form.authenticator в брандмауэре, который проверяет каждый логин.

Я пытаюсь выяснить, как заставить пользователя выйти из системы, пока он еще в системе.
Рассмотрим следующий сценарий:

  1. Пользователь входит в систему, пока его учетная запись еще активна.
  2. Администратор деактивирует учетную запись пользователя.
  3. Пользователь вышел из системы из-за того, что он больше не активен.

К сожалению, шаг № 3 не происходит. Причина может заключаться в том, что пользователь уже получил токен и считается «переадресованным» Symfony 2.5брандмауэр (вероятно, токен кэшируется в контексте безопасности?).

Мне интересно, что было бы лучшим способом преодолеть эту проблему? Должен ли я написать слушатель события ядра или, возможно, Пользовательский провайдер?

3

Решение

Вы можете прекратить сеанс пользователя с помощью следующих двух строк (если у вас есть доступ к контейнеру, в противном случае вы должны ввести security.context а также session):

$container->get('security.context')->setToken(null);
$container->get('session')->invalidate();

После этого пользователь должен выйти из системы.

Если вы ранее загружали пользовательский объект, вы можете также сбросить его.

6

Другие решения

Хотя @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 }

И как только пользователь будет деактивирован, он будет принудительно перенаправлен на страницу входа в систему вашего брандмауэра. Надеюсь, это кому-нибудь поможет.

5