Use the firewall event dispatcher

This commit is contained in:
Wouter de Jong 2020-04-04 17:37:52 +02:00
parent 95edc806a1
commit 7ef6a7ab03
6 changed files with 26 additions and 38 deletions

View File

@ -218,9 +218,8 @@ class RememberMeFactory implements SecurityFactoryInterface, AuthenticatorFactor
{
$container
->setDefinition('security.listener.remember_me.'.$id, new ChildDefinition('security.listener.remember_me'))
->addTag('kernel.event_subscriber')
->addTag('kernel.event_subscriber', ['dispatcher' => 'security.event_dispatcher.'.$id])
->replaceArgument(0, new Reference($rememberMeServicesId))
->replaceArgument(1, $id)
;
$container

View File

@ -156,8 +156,11 @@ class SecurityExtension extends Extension implements PrependExtensionInterface
->replaceArgument(2, $this->statelessFirewallKeys);
if ($this->authenticatorManagerEnabled) {
$container->getDefinition(SessionListener::class)
->replaceArgument(1, $this->statelessFirewallKeys);
foreach ($this->statelessFirewallKeys as $statelessFirewallId) {
$container
->setDefinition('security.listener.session.'.$statelessFirewallId, new ChildDefinition('security.listener.session'))
->addTag('kernel.event_subscriber', ['dispatcher' => 'security.event_dispatcher.'.$statelessFirewallId]);
}
}
if ($config['encoders']) {
@ -446,6 +449,7 @@ class SecurityExtension extends Extension implements PrependExtensionInterface
$container
->setDefinition($managerId = 'security.authenticator.manager.'.$id, new ChildDefinition('security.authenticator.manager'))
->replaceArgument(0, $authenticators)
->replaceArgument(2, new Reference($firewallEventDispatcherId))
->replaceArgument(3, $id)
->addTag('monolog.logger', ['channel' => 'security'])
;

View File

@ -12,7 +12,10 @@
namespace Symfony\Bundle\SecurityBundle\EventListener;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Security\Http\Event\LoginFailureEvent;
use Symfony\Component\Security\Http\Event\LoginSuccessEvent;
use Symfony\Component\Security\Http\Event\LogoutEvent;
use Symfony\Component\Security\Http\Event\VerifyAuthenticatorCredentialsEvent;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
/**
@ -34,6 +37,9 @@ class FirewallEventBubblingListener implements EventSubscriberInterface
{
return [
LogoutEvent::class => 'bubbleEvent',
LoginFailureEvent::class => 'bubbleEvent',
LoginSuccessEvent::class => 'bubbleEvent',
VerifyAuthenticatorCredentialsEvent::class => 'bubbleEvent',
];
}

View File

@ -59,8 +59,9 @@
<argument type="service" id="Symfony\Component\Security\Core\User\UserCheckerInterface" />
</service>
<service id="security.listener.session" class="Symfony\Component\Security\Http\EventListener\SessionStrategyListener">
<tag name="kernel.event_subscriber" />
<service id="security.listener.session"
class="Symfony\Component\Security\Http\EventListener\SessionStrategyListener"
abstract="true">
<argument type="service" id="security.authentication.session_strategy" />
<argument type="abstract">stateless firewall keys</argument>
</service>

View File

@ -26,26 +26,29 @@ use Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface;
class RememberMeListener implements EventSubscriberInterface
{
private $rememberMeServices;
private $providerKey;
private $logger;
public function __construct(RememberMeServicesInterface $rememberMeServices, string $providerKey, ?LoggerInterface $logger = null)
public function __construct(RememberMeServicesInterface $rememberMeServices, ?LoggerInterface $logger = null)
{
$this->rememberMeServices = $rememberMeServices;
$this->providerKey = $providerKey;
$this->logger = $logger;
}
public function onSuccessfulLogin(LoginSuccessEvent $event): void
{
if (!$this->isRememberMeEnabled($event->getProviderKey(), $event->getAuthenticator())) {
$authenticator = $event->getAuthenticator();
if (!$authenticator instanceof RememberMeAuthenticatorInterface || !$authenticator->supportsRememberMe()) {
if (null !== $this->logger) {
$this->logger->debug('Remember me skipped: your authenticator does not support it.', ['authenticator' => \get_class($authenticator)]);
}
return;
}
if (null === $event->getResponse()) {
if (null !== $this->logger) {
$this->logger->debug('Remember me skipped: the authenticator did not set a success response.', ['authenticator' => \get_class($event->getAuthenticator())]);
$this->logger->debug('Remember me skipped: the authenticator did not set a success response.', ['authenticator' => \get_class($authenticator)]);
}
return;
@ -56,31 +59,9 @@ class RememberMeListener implements EventSubscriberInterface
public function onFailedLogin(LoginFailureEvent $event): void
{
if (!$this->isRememberMeEnabled($event->getProviderKey())) {
return;
}
$this->rememberMeServices->loginFail($event->getRequest(), $event->getException());
}
private function isRememberMeEnabled(string $providerKey, ?AuthenticatorInterface $authenticator = null): bool
{
if ($providerKey !== $this->providerKey) {
// This listener is created for a different firewall.
return false;
}
if (null !== $authenticator && (!$authenticator instanceof RememberMeAuthenticatorInterface || !$authenticator->supportsRememberMe())) {
if (null !== $this->logger) {
$this->logger->debug('Remember me skipped: your authenticator does not support it.', ['authenticator' => \get_class($authenticator)]);
}
return false;
}
return true;
}
public static function getSubscribedEvents(): array
{
return [

View File

@ -28,21 +28,18 @@ use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterfa
class SessionStrategyListener implements EventSubscriberInterface
{
private $sessionAuthenticationStrategy;
private $statelessProviderKeys;
public function __construct(SessionAuthenticationStrategyInterface $sessionAuthenticationStrategy, array $statelessProviderKeys = [])
public function __construct(SessionAuthenticationStrategyInterface $sessionAuthenticationStrategy)
{
$this->sessionAuthenticationStrategy = $sessionAuthenticationStrategy;
$this->statelessProviderKeys = $statelessProviderKeys;
}
public function onSuccessfulLogin(LoginSuccessEvent $event): void
{
$request = $event->getRequest();
$token = $event->getAuthenticatedToken();
$providerKey = $event->getProviderKey();
if (!$request->hasSession() || !$request->hasPreviousSession() || \in_array($providerKey, $this->statelessProviderKeys, true)) {
if (!$request->hasSession() || !$request->hasPreviousSession()) {
return;
}