简体   繁体   English

Symfony Security注销未清除RememberMe令牌

[英]Symfony Security logout not clearing RememberMe token

Using Symfony 4 with a security.yaml like this: 将Symfony 4与security.yaml一起使用,如下所示:

encoders:
  App\Entity\User: sha256
providers:
    public_users:
      entity:
        class: App\Entity\User
        property: email
firewalls:
    dev:
        pattern: ^/(_(profiler|wdt)|css|images|js)/
        security: false
    main:
        pattern: ^/

        anonymous: ~

        form_login:
          login_path: login
          remember_me:    true

        remember_me:
            secret: "%kernel.secret%"
            name:  relevea_remember_me
            lifetime: 864000
            always_remember_me: false
            remember_me_parameter: user_login[stayConnected]

        logout:
            path: logout
            target: /about
            invalidate_session: false

access_control:
  - { path: ^/auth, roles: IS_AUTHENTICATED_ANONYMOUSLY }

logout operation is not clearing the rememberMe token. logout操作不会清除RememberMe令牌。

I can see that LogoutListener ( https://github.com/symfony/security/blob/master/Http/Firewall/LogoutListener.php ) is called after RememberMeListener ( https://github.com/symfony/security/blob/master/Http/Firewall/RememberMeListener.php ) so for LogoutListener, the token is null and nothing is cleared :/ 我可以看到LogoutListenerhttps://github.com/symfony/security/blob/master/Http/Firewall/LogoutListener.php )之后被称为RememberMeListenerhttps://github.com/symfony/security/blob/master /Http/Firewall/RememberMeListener.php ),因此对于LogoutListener而言,令牌为null,并且不会清除任何内容:/

The listeners list from TraceableFirewallListener : TraceableFirewallListener的侦听器列表:

Symfony\\Component\\Security\\Http\\Firewall\\ChannelListener Symfony\\Component\\Security\\Http\\Firewall\\ContextListener Symfony\\Component\\Security\\Http\\Firewall\\LogoutListener Symfony \\ Component \\ Security \\ Http \\ Firewall \\ ChannelListener Symfony \\ Component \\ Security \\ Http \\ Firewall \\ ContextListener Symfony \\ Component \\ Security \\ Http \\ Firewall \\ LogoutListener

Symfony\\Component\\Security\\Http\\Firewall\\UsernamePasswordFormAuthenticationListener Symfony\\Component\\Security\\Http\\Firewall\\RememberMeListener Symfony \\ Component \\ Security \\ Http \\ Firewall \\ UsernamePasswordFormAuthenticationListener Symfony \\ Component \\ Security \\ Http \\ Firewall \\ RememberMeListener

Symfony\\Component\\Security\\Http\\Firewall\\AnonymousAuthenticationListener Symfony\\Component\\Security\\Http\\Firewall\\AccessListener Symfony \\ Component \\ Security \\ Http \\ Firewall \\ AnonymousAuthenticationListener Symfony \\ Component \\ Security \\ Http \\ Firewall \\ AccessListener

Why the logout listener is before others? 为什么注销侦听器先于其他侦听器?

It looks a known issue since ... 2013! 自2013年以来看起来是一个已知问题!

https://github.com/symfony/symfony/issues/7104 https://github.com/symfony/symfony/issues/7104

So basically, you cant logout from a RememberMe token :/ 因此,基本上,您不能从RememberMe令牌中注销:/

You can override the firewall listener to call logout listener the last as below 您可以覆盖防火墙侦听器以调用注销侦听器,如下所示

security.firewall:
    class: AppBundle\Security\FirewallListener
    arguments:
       - '@security.firewall.map'
       - '@event_dispatcher'
       - '@security.logout_url_generator'
    tags:
       - { name: kernel.event_subscriber }


use Symfony\Bundle\SecurityBundle\Security\FirewallMap;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpKernel\Event\FinishRequestEvent;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\Security\Http\Firewall;
use Symfony\Component\Security\Http\Firewall\LogoutListener;
use Symfony\Component\Security\Http\FirewallMapInterface;
use Symfony\Component\Security\Http\Logout\LogoutUrlGenerator;

class FirewallListener extends Firewall
{
    private $map;
    private $exceptionListeners;
    private $logoutUrlGenerator;
    private $dispatcher;

    public function __construct(FirewallMapInterface $map, EventDispatcherInterface $dispatcher, LogoutUrlGenerator $logoutUrlGenerator)
    {
        $this->map = $map;
        $this->dispatcher = $dispatcher;
        $this->exceptionListeners = new \SplObjectStorage();
        $this->logoutUrlGenerator = $logoutUrlGenerator;

        parent::__construct($map, $dispatcher);
    }

    /**
     * {@inheritdoc}
     */
    public function onKernelRequest(GetResponseEvent $event)
    {
        if (!$event->isMasterRequest()) {
            return;
        }
        if ($this->map instanceof FirewallMap && $config = $this->map->getFirewallConfig($event->getRequest())) {
            $this->logoutUrlGenerator->setCurrentFirewall($config->getName(), $config->getContext());
        }

        // register listeners for this firewall
        list($listeners, $exceptionListener) = $this->map->getListeners($event->getRequest());
        if (null !== $exceptionListener) {
            $this->exceptionListeners[$event->getRequest()] = $exceptionListener;
            $exceptionListener->register($this->dispatcher);
        }

        // initiate the listener chain
        $logoutListener = null;
        foreach ($listeners as $listener) {
            if ($listener instanceof LogoutListener) {
                $logoutListener = $listener;
                continue;
            }

            $listener->handle($event);

            if ($event->hasResponse()) {
                break;
            }
        }

        if ($logoutListener) {
            $logoutListener->handle($event);
        }
    }

    /**
     * {@inheritdoc}
     */
    public function onKernelFinishRequest(FinishRequestEvent $event)
    {
        if ($event->isMasterRequest()) {
            $this->logoutUrlGenerator->setCurrentFirewall(null);
        }

        parent::onKernelFinishRequest($event);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM