Use the firewall event dispatcher
This commit is contained in:
parent
95edc806a1
commit
7ef6a7ab03
@ -218,9 +218,8 @@ class RememberMeFactory implements SecurityFactoryInterface, AuthenticatorFactor
|
|||||||
{
|
{
|
||||||
$container
|
$container
|
||||||
->setDefinition('security.listener.remember_me.'.$id, new ChildDefinition('security.listener.remember_me'))
|
->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(0, new Reference($rememberMeServicesId))
|
||||||
->replaceArgument(1, $id)
|
|
||||||
;
|
;
|
||||||
|
|
||||||
$container
|
$container
|
||||||
|
@ -156,8 +156,11 @@ class SecurityExtension extends Extension implements PrependExtensionInterface
|
|||||||
->replaceArgument(2, $this->statelessFirewallKeys);
|
->replaceArgument(2, $this->statelessFirewallKeys);
|
||||||
|
|
||||||
if ($this->authenticatorManagerEnabled) {
|
if ($this->authenticatorManagerEnabled) {
|
||||||
$container->getDefinition(SessionListener::class)
|
foreach ($this->statelessFirewallKeys as $statelessFirewallId) {
|
||||||
->replaceArgument(1, $this->statelessFirewallKeys);
|
$container
|
||||||
|
->setDefinition('security.listener.session.'.$statelessFirewallId, new ChildDefinition('security.listener.session'))
|
||||||
|
->addTag('kernel.event_subscriber', ['dispatcher' => 'security.event_dispatcher.'.$statelessFirewallId]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($config['encoders']) {
|
if ($config['encoders']) {
|
||||||
@ -446,6 +449,7 @@ class SecurityExtension extends Extension implements PrependExtensionInterface
|
|||||||
$container
|
$container
|
||||||
->setDefinition($managerId = 'security.authenticator.manager.'.$id, new ChildDefinition('security.authenticator.manager'))
|
->setDefinition($managerId = 'security.authenticator.manager.'.$id, new ChildDefinition('security.authenticator.manager'))
|
||||||
->replaceArgument(0, $authenticators)
|
->replaceArgument(0, $authenticators)
|
||||||
|
->replaceArgument(2, new Reference($firewallEventDispatcherId))
|
||||||
->replaceArgument(3, $id)
|
->replaceArgument(3, $id)
|
||||||
->addTag('monolog.logger', ['channel' => 'security'])
|
->addTag('monolog.logger', ['channel' => 'security'])
|
||||||
;
|
;
|
||||||
|
@ -12,7 +12,10 @@
|
|||||||
namespace Symfony\Bundle\SecurityBundle\EventListener;
|
namespace Symfony\Bundle\SecurityBundle\EventListener;
|
||||||
|
|
||||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
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\LogoutEvent;
|
||||||
|
use Symfony\Component\Security\Http\Event\VerifyAuthenticatorCredentialsEvent;
|
||||||
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
|
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -34,6 +37,9 @@ class FirewallEventBubblingListener implements EventSubscriberInterface
|
|||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
LogoutEvent::class => 'bubbleEvent',
|
LogoutEvent::class => 'bubbleEvent',
|
||||||
|
LoginFailureEvent::class => 'bubbleEvent',
|
||||||
|
LoginSuccessEvent::class => 'bubbleEvent',
|
||||||
|
VerifyAuthenticatorCredentialsEvent::class => 'bubbleEvent',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,8 +59,9 @@
|
|||||||
<argument type="service" id="Symfony\Component\Security\Core\User\UserCheckerInterface" />
|
<argument type="service" id="Symfony\Component\Security\Core\User\UserCheckerInterface" />
|
||||||
</service>
|
</service>
|
||||||
|
|
||||||
<service id="security.listener.session" class="Symfony\Component\Security\Http\EventListener\SessionStrategyListener">
|
<service id="security.listener.session"
|
||||||
<tag name="kernel.event_subscriber" />
|
class="Symfony\Component\Security\Http\EventListener\SessionStrategyListener"
|
||||||
|
abstract="true">
|
||||||
<argument type="service" id="security.authentication.session_strategy" />
|
<argument type="service" id="security.authentication.session_strategy" />
|
||||||
<argument type="abstract">stateless firewall keys</argument>
|
<argument type="abstract">stateless firewall keys</argument>
|
||||||
</service>
|
</service>
|
||||||
|
@ -26,26 +26,29 @@ use Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface;
|
|||||||
class RememberMeListener implements EventSubscriberInterface
|
class RememberMeListener implements EventSubscriberInterface
|
||||||
{
|
{
|
||||||
private $rememberMeServices;
|
private $rememberMeServices;
|
||||||
private $providerKey;
|
|
||||||
private $logger;
|
private $logger;
|
||||||
|
|
||||||
public function __construct(RememberMeServicesInterface $rememberMeServices, string $providerKey, ?LoggerInterface $logger = null)
|
public function __construct(RememberMeServicesInterface $rememberMeServices, ?LoggerInterface $logger = null)
|
||||||
{
|
{
|
||||||
$this->rememberMeServices = $rememberMeServices;
|
$this->rememberMeServices = $rememberMeServices;
|
||||||
$this->providerKey = $providerKey;
|
|
||||||
$this->logger = $logger;
|
$this->logger = $logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function onSuccessfulLogin(LoginSuccessEvent $event): void
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (null === $event->getResponse()) {
|
if (null === $event->getResponse()) {
|
||||||
if (null !== $this->logger) {
|
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;
|
return;
|
||||||
@ -56,31 +59,9 @@ class RememberMeListener implements EventSubscriberInterface
|
|||||||
|
|
||||||
public function onFailedLogin(LoginFailureEvent $event): void
|
public function onFailedLogin(LoginFailureEvent $event): void
|
||||||
{
|
{
|
||||||
if (!$this->isRememberMeEnabled($event->getProviderKey())) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->rememberMeServices->loginFail($event->getRequest(), $event->getException());
|
$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
|
public static function getSubscribedEvents(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
|
@ -28,21 +28,18 @@ use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterfa
|
|||||||
class SessionStrategyListener implements EventSubscriberInterface
|
class SessionStrategyListener implements EventSubscriberInterface
|
||||||
{
|
{
|
||||||
private $sessionAuthenticationStrategy;
|
private $sessionAuthenticationStrategy;
|
||||||
private $statelessProviderKeys;
|
|
||||||
|
|
||||||
public function __construct(SessionAuthenticationStrategyInterface $sessionAuthenticationStrategy, array $statelessProviderKeys = [])
|
public function __construct(SessionAuthenticationStrategyInterface $sessionAuthenticationStrategy)
|
||||||
{
|
{
|
||||||
$this->sessionAuthenticationStrategy = $sessionAuthenticationStrategy;
|
$this->sessionAuthenticationStrategy = $sessionAuthenticationStrategy;
|
||||||
$this->statelessProviderKeys = $statelessProviderKeys;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onSuccessfulLogin(LoginSuccessEvent $event): void
|
public function onSuccessfulLogin(LoginSuccessEvent $event): void
|
||||||
{
|
{
|
||||||
$request = $event->getRequest();
|
$request = $event->getRequest();
|
||||||
$token = $event->getAuthenticatedToken();
|
$token = $event->getAuthenticatedToken();
|
||||||
$providerKey = $event->getProviderKey();
|
|
||||||
|
|
||||||
if (!$request->hasSession() || !$request->hasPreviousSession() || \in_array($providerKey, $this->statelessProviderKeys, true)) {
|
if (!$request->hasSession() || !$request->hasPreviousSession()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user