Выйти из системы в приложении Symfony 2, когда включена опция «запомнить меня»

Я ищу способ зарегистрировать пользователя из приложения Symfony 2, но не смог найти способ сделать это правильно.

Я пробовал описанный здесь подход: Symfony2: как вручную вывести пользователя вручную в контроллер?

$this->get('security.context')->setToken(null); $this->get('request')->getSession()->invalidate(); 

Он работает нормально, когда « запомнить меня » отключен, однако, когда я его включаю, он не работает. Похоже, что пользователь автоматически повторно аутентифицируется обратно этим куки-файлом.

 remember_me: key: "%secret%" lifetime: 31536000 path: / domain: ~ always_remember_me: true 

Каков правильный способ регистрации пользователя из приложения Symfony 2? Нужно ли дополнительно удалить этот файл cookie с сервера?

Возможно, вам придется явно вызвать метод save() ( Documentation ) сеансового хранилища.

Заставить сеанс сохранять и закрывать.

Кроме того, вы можете попросить удалить сеанс – и / или remember_me -cookies через заголовки ответов.

Имя сессии -cookie настраивается как контейнер-параметр framework.session.name и по умолчанию имеет значение session.name из вашего php.ini .

 $cookieName = $this->container->getParameter('framework.session.name'); $response->headers->clearCookie( $cookieName ); 

Имя memory_me -cookie можно настроить в вашей конфигурации security .

 security: firewalls: your_firewall: remember_me: name: neverforget # <- cookie-name 

Благодаря @nifr я смог решить эту проблему. Вот пулебезопасное пошаговое руководство для входа пользователя из приложения Symfony 2 вручную.

Предупреждение

Symfony уже реализует функции регистрации пользователя и удаления файлов cookie. Существует LogoutListener который делегирует эти действия для пары обработчиков выхода: CookieClearingLogoutHandler и SessionLogoutHandler . Я думаю, что лучший способ действий – назвать этих обработчиков, а не реализовывать такую ​​низкоуровневую логику самостоятельно. Однако я не могу найти способ сделать это.

Решение

Это решение для Symfony 2.6. Разница заключается в security.token_storage .

  1. Добавьте два дополнительных параметра для хранения имен файлов cookie для «session» и «Remember me» для ваших parameters.yml :
 # parameters.yml parameters: session.name: SESS session.remember_me.name: LONGSESS 
  1. Обновите файл config.yml чтобы использовать первый параметр для имени сеанса:
 # config.yml framework: session: name: "%session.name%" 
  1. Обновите свой security.yml чтобы использовать второй параметр для запоминания имени сеанса:
 # security.yml security: firewalls: demo_secured_area: remember_me: name: "%session.remember_me.name%" 
  1. Вот код, который вы можете использовать для регистрации текущего пользователя:

Вы можете использовать такой код внутри прослушивателя событий ядра, если хотите.

 // SomeController.php /** * @Route("/terminate", name="app.terminate") */ public function terminateAction() { // Logging user out. $this->get('security.token_storage')->setToken(null); // Invalidating the session. $session = $this->get('request')->getSession(); $session->invalidate(); // Redirecting user to login page in the end. $response = $this->redirectToRoute('app.login'); // Clearing the cookies. $cookieNames = [ $this->container->getParameter('session.name'), $this->container->getParameter('session.remember_me.name'), ]; foreach ($cookieNames as $cookieName) { $response->headers->clearCookie($cookieName); } return $response; } 

Вот реализация прослушивателя событий ядра, который заставит пользователей выйти из строя на основе свойства entity: Запуск пользователя из приложения Symfony 2 с помощью прослушивателя событий ядра .

Я надеюсь, что это помогает.

@ Слав Фомин II

Symfony уже реализует функции регистрации пользователя и удаления файлов cookie. Существует LogoutListener, который делегирует эти действия для пары обработчиков выхода: CookieClearingLogoutHandler и SessionLogoutHandler. Я думаю, что лучший способ действий – назвать этих обработчиков, а не реализовывать такую ​​низкоуровневую логику самостоятельно. Однако я не могу найти способ сделать это.

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

Я просмотрел Symfony\Component\Security\Http\Firewall\LogoutListener и протестировал его, что он вызывает 2 службы во время выхода из системы (Symfony 3.2.9).

$tokenBasedRememberMeServices , кстати, удаляет cookie с $tokenBasedRememberMeServices .

 <?php declare(strict_types=1); namespace MyProject\Security\Listener; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage; use Symfony\Component\Security\Http\Logout\DefaultLogoutSuccessHandler; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Security\Http\Logout\SessionLogoutHandler; use Symfony\Component\Security\Http\RememberMe\TokenBasedRememberMeServices; final class LogoutListener { private $sessionLogoutHandler; private $tokenBasedRememberMeServices; private $defaultLogoutSuccessHandler; private $tokenStorage; public function __construct( SessionLogoutHandler $sessionLogoutHandler, TokenBasedRememberMeServices $tokenBasedRememberMeServices, DefaultLogoutSuccessHandler $defaultLogoutSuccessHandler, TokenStorage $tokenStorage ) { $this->sessionLogoutHandler = $sessionLogoutHandler; $this->tokenBasedRememberMeServices = $tokenBasedRememberMeServices; $this->defaultLogoutSuccessHandler = $defaultLogoutSuccessHandler; $this->tokenStorage = $tokenStorage; } public function logout(Request $request): void { $token = $this->tokenStorage->getToken(); $response = $this->defaultLogoutSuccessHandler->onLogoutSuccess($request); $this->sessionLogoutHandler->logout($request, $response, $token); $this->tokenBasedRememberMeServices->logout($request, $response, $token); } }