Symfony Security注销未清除RememberMe令牌 [英] Symfony Security logout not clearing RememberMe token

查看:166
本文介绍了Symfony Security注销未清除RememberMe令牌的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

将Symfony 4与security.yaml一起使用:

Using Symfony 4 with a security.yaml like this:

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操作未清除RememberMe令牌.

logoutoperation is not clearing the rememberMe token.

我可以看到LogoutListener( https:/在RememberMeListener(/master/Http/Firewall/RememberMeListener.php"rel =" nofollow noreferrer> https://github.com/symfony/security/blob/master/Http/Firewall/RememberMeListener.php ),因此对于LogoutListener,令牌为空且未清除任何内容:/

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 :/

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?

推荐答案

您可以覆盖防火墙侦听器以最后一次退出注销侦听器

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

这篇关于Symfony Security注销未清除RememberMe令牌的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆