Log user out in Symfony 2 application when “remember me” is enabled

后端 未结 3 1366
孤街浪徒
孤街浪徒 2020-12-09 19:55

I\'m looking for a way to log user out of Symfony 2 application, but could not find a way to do it properly.

I\'ve tried an approach described here: Symfony2: how to

相关标签:
3条回答
  • 2020-12-09 20:34

    Thanks to @nifr I was able to resolve this issue. Here's the bulletproof step-by-step guide to log user out of Symfony 2 application manually.

    Warning

    Symfony already implements the functionality of logging user out and deleting cookies. There is a LogoutListener who delegates those action to couple of logout handlers: CookieClearingLogoutHandler and SessionLogoutHandler. I think the best course of action would be to call those handlers and not to implement such low-level logic yourself. However, I can't find a way to do this.

    Solution

    This solution is for Symfony 2.6. The difference is in security.token_storage.

    1. Add two additional parameters to store cookie names for «session» and «remember me» to your parameters.yml:
    # parameters.yml
    
    parameters:
        session.name: SESS
        session.remember_me.name: LONGSESS
    
    1. Update your config.yml to use the first parameter for session name:
    # config.yml
    
    framework:
        session:
            name: "%session.name%"
    
    1. Update your security.yml to use the second parameter for remember me session name:
    # security.yml
    
    security:
        firewalls:
            demo_secured_area:
                remember_me:
                    name: "%session.remember_me.name%"
    
    1. Here's the code you can use to log current user out:

    You can use such code inside of a kernel event listener, if you want so.

    // 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;
    }
    

    Here's the implementation of kernel event listener which will force users to log out basing on entity property: Logging user out of Symfony 2 application using kernel event listener.

    I hope it helps.

    0 讨论(0)
  • 2020-12-09 20:41

    @Slava Fomin II

    Symfony already implements the functionality of logging user out and deleting cookies. There is a LogoutListener who delegates those action to couple of logout handlers: CookieClearingLogoutHandler and SessionLogoutHandler. I think the best course of action would be to call those handlers and not to implement such low-level logic yourself. However, I can't find a way to do this.

    Why not simply create a service that calls those?

    I looked into Symfony\Component\Security\Http\Firewall\LogoutListener and tested that he calls 2 services during logout (Symfony 3.2.9).

    $tokenBasedRememberMeServices by the way deletes the remember-me cookie.

    <?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);
        }
    
    }
    
    0 讨论(0)
  • 2020-12-09 20:49

    You may have to call the session-storage's save() (Documentation) method explicitly.

    Force the session to be saved and closed.

    Further you can request to delete the session- and/or remember_me-cookies via response headers.

    The session-cookie's name is configured as the container-parameter framework.session.name and defaults to the session.name value from your php.ini.

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

    The remember_me-cookie's name can be configured in your security configuration.

    security:
        firewalls:
            your_firewall:
                remember_me: 
                    name: neverforget # <- cookie-name
    
    0 讨论(0)
提交回复
热议问题