Symfony Security注销未清除RememberMe令牌 [英] Symfony Security logout not clearing RememberMe token
问题描述
将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令牌.
logout
operation is not clearing the rememberMe token.
我可以看到LogoutListener
( https:/在RememberMeListener
(
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屋!