Use one AuthenticatorManager per firewall
This commit is contained in:
parent
09bed16d3d
commit
44cc76fec2
@ -23,6 +23,7 @@ use Symfony\Component\Config\FileLocator;
|
|||||||
use Symfony\Component\Console\Application;
|
use Symfony\Component\Console\Application;
|
||||||
use Symfony\Component\DependencyInjection\Alias;
|
use Symfony\Component\DependencyInjection\Alias;
|
||||||
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
|
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
|
||||||
|
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
|
||||||
use Symfony\Component\DependencyInjection\ChildDefinition;
|
use Symfony\Component\DependencyInjection\ChildDefinition;
|
||||||
use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass;
|
use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass;
|
||||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||||
@ -278,19 +279,16 @@ class SecurityExtension extends Extension implements PrependExtensionInterface
|
|||||||
$mapDef->replaceArgument(0, ServiceLocatorTagPass::register($container, $contextRefs));
|
$mapDef->replaceArgument(0, ServiceLocatorTagPass::register($container, $contextRefs));
|
||||||
$mapDef->replaceArgument(1, new IteratorArgument($map));
|
$mapDef->replaceArgument(1, new IteratorArgument($map));
|
||||||
|
|
||||||
// add authentication providers to authentication manager
|
if (!$this->authenticatorManagerEnabled) {
|
||||||
$authenticationProviders = array_map(function ($id) {
|
// add authentication providers to authentication manager
|
||||||
return new Reference($id);
|
$authenticationProviders = array_map(function ($id) {
|
||||||
}, array_unique($authenticationProviders));
|
return new Reference($id);
|
||||||
$authenticationManagerId = 'security.authentication.manager.provider';
|
}, array_unique($authenticationProviders));
|
||||||
if ($this->authenticatorManagerEnabled) {
|
|
||||||
$authenticationManagerId = 'security.authentication.manager.authenticator';
|
$container
|
||||||
$container->setAlias('security.authentication.manager', new Alias($authenticationManagerId));
|
->getDefinition('security.authentication.manager')
|
||||||
|
->replaceArgument(0, new IteratorArgument($authenticationProviders));
|
||||||
}
|
}
|
||||||
$container
|
|
||||||
->getDefinition($authenticationManagerId)
|
|
||||||
->replaceArgument(0, new IteratorArgument($authenticationProviders))
|
|
||||||
;
|
|
||||||
|
|
||||||
// register an autowire alias for the UserCheckerInterface if no custom user checker service is configured
|
// register an autowire alias for the UserCheckerInterface if no custom user checker service is configured
|
||||||
if (!$customUserChecker) {
|
if (!$customUserChecker) {
|
||||||
@ -441,17 +439,28 @@ class SecurityExtension extends Extension implements PrependExtensionInterface
|
|||||||
$authenticationProviders = array_merge($authenticationProviders, $firewallAuthenticationProviders);
|
$authenticationProviders = array_merge($authenticationProviders, $firewallAuthenticationProviders);
|
||||||
|
|
||||||
if ($this->authenticatorManagerEnabled) {
|
if ($this->authenticatorManagerEnabled) {
|
||||||
|
// authenticator manager
|
||||||
|
$authenticators = array_map(function ($id) {
|
||||||
|
return new Reference($id);
|
||||||
|
}, $firewallAuthenticationProviders);
|
||||||
|
$container
|
||||||
|
->setDefinition($managerId = 'security.authenticator.manager.'.$id, new ChildDefinition('security.authentication.manager.authenticator'))
|
||||||
|
->replaceArgument(0, $authenticators)
|
||||||
|
;
|
||||||
|
|
||||||
|
$managerLocator = $container->getDefinition('security.authenticator.managers_locator');
|
||||||
|
$managerLocator->replaceArgument(0, array_merge($managerLocator->getArgument(0), [$id => new ServiceClosureArgument(new Reference($managerId))]));
|
||||||
|
|
||||||
// authenticator manager listener
|
// authenticator manager listener
|
||||||
$container
|
$container
|
||||||
->setDefinition('security.firewall.authenticator.'.$id.'.locator', new ChildDefinition('security.firewall.authenticator.locator'))
|
->setDefinition('security.firewall.authenticator.'.$id.'.locator', new ChildDefinition('security.firewall.authenticator.locator'))
|
||||||
->setArguments([array_map(function ($id) {
|
->setArguments([$authenticators])
|
||||||
return new Reference($id);
|
|
||||||
}, $firewallAuthenticationProviders)])
|
|
||||||
->addTag('container.service_locator')
|
->addTag('container.service_locator')
|
||||||
;
|
;
|
||||||
|
|
||||||
$container
|
$container
|
||||||
->setDefinition('security.firewall.authenticator.'.$id, new ChildDefinition('security.firewall.authenticator'))
|
->setDefinition('security.firewall.authenticator.'.$id, new ChildDefinition('security.firewall.authenticator'))
|
||||||
|
->replaceArgument(0, new Reference($managerId))
|
||||||
->replaceArgument(2, new Reference('security.firewall.authenticator.'.$id.'.locator'))
|
->replaceArgument(2, new Reference('security.firewall.authenticator.'.$id.'.locator'))
|
||||||
->replaceArgument(3, $id)
|
->replaceArgument(3, $id)
|
||||||
;
|
;
|
||||||
|
@ -6,7 +6,10 @@
|
|||||||
<services>
|
<services>
|
||||||
<!-- Manager -->
|
<!-- Manager -->
|
||||||
|
|
||||||
<service id="security.authentication.manager.authenticator" class="Symfony\Component\Security\Http\Authentication\AuthenticatorManager">
|
<service id="security.authentication.manager.authenticator"
|
||||||
|
class="Symfony\Component\Security\Http\Authentication\AuthenticatorManager"
|
||||||
|
abstract="true"
|
||||||
|
>
|
||||||
<argument type="abstract">authenticators</argument>
|
<argument type="abstract">authenticators</argument>
|
||||||
<argument type="service" id="event_dispatcher" />
|
<argument type="service" id="event_dispatcher" />
|
||||||
<argument>%security.authentication.manager.erase_credentials%</argument>
|
<argument>%security.authentication.manager.erase_credentials%</argument>
|
||||||
@ -14,6 +17,18 @@
|
|||||||
<argument type="service" id="event_dispatcher" />
|
<argument type="service" id="event_dispatcher" />
|
||||||
</call>
|
</call>
|
||||||
</service>
|
</service>
|
||||||
|
|
||||||
|
<service id="security.authenticator.managers_locator"
|
||||||
|
class="Symfony\Component\DependencyInjection\ServiceLocator">
|
||||||
|
<argument type="collection" />
|
||||||
|
</service>
|
||||||
|
|
||||||
|
<service id="security.authentication.manager"
|
||||||
|
class="Symfony\Bundle\SecurityBundle\Security\FirewallAwareAuthenticatorManager">
|
||||||
|
<argument type="service" id="security.firewall.map" />
|
||||||
|
<argument type="service" id="security.authenticator.managers_locator" />
|
||||||
|
<argument type="service" id="request_stack" />
|
||||||
|
</service>
|
||||||
<service id="Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface" alias="security.authentication.manager" />
|
<service id="Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface" alias="security.authentication.manager" />
|
||||||
|
|
||||||
<service id="security.authenticator_handler"
|
<service id="security.authenticator_handler"
|
||||||
@ -35,7 +50,7 @@
|
|||||||
class="Symfony\Bundle\SecurityBundle\EventListener\LazyAuthenticatorManagerListener"
|
class="Symfony\Bundle\SecurityBundle\EventListener\LazyAuthenticatorManagerListener"
|
||||||
abstract="true">
|
abstract="true">
|
||||||
<tag name="monolog.logger" channel="security" />
|
<tag name="monolog.logger" channel="security" />
|
||||||
<argument type="service" id="security.authentication.manager" />
|
<argument type="abstract">authenticator manager</argument>
|
||||||
<argument type="service" id="security.authenticator_handler" />
|
<argument type="service" id="security.authenticator_handler" />
|
||||||
<argument/> <!-- authenticator locator -->
|
<argument/> <!-- authenticator locator -->
|
||||||
<argument/> <!-- provider key -->
|
<argument/> <!-- provider key -->
|
||||||
|
@ -0,0 +1,48 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Bundle\SecurityBundle\Security;
|
||||||
|
|
||||||
|
use Symfony\Component\DependencyInjection\ServiceLocator;
|
||||||
|
use Symfony\Component\HttpFoundation\RequestStack;
|
||||||
|
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
|
||||||
|
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||||
|
use Symfony\Component\Security\Core\Exception\LogicException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A decorator that delegates all method calls to the authenticator
|
||||||
|
* manager of the current firewall.
|
||||||
|
*
|
||||||
|
* @author Wouter de Jong <wouter@wouterj.nl>
|
||||||
|
*/
|
||||||
|
class FirewallAwareAuthenticatorManager implements AuthenticationManagerInterface
|
||||||
|
{
|
||||||
|
private $firewallMap;
|
||||||
|
private $authenticatorManagers;
|
||||||
|
private $requestStack;
|
||||||
|
|
||||||
|
public function __construct(FirewallMap $firewallMap, ServiceLocator $authenticatorManagers, RequestStack $requestStack)
|
||||||
|
{
|
||||||
|
$this->firewallMap = $firewallMap;
|
||||||
|
$this->authenticatorManagers = $authenticatorManagers;
|
||||||
|
$this->requestStack = $requestStack;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function authenticate(TokenInterface $token)
|
||||||
|
{
|
||||||
|
$firewallConfig = $this->firewallMap->getFirewallConfig($this->requestStack->getMasterRequest());
|
||||||
|
if (null === $firewallConfig) {
|
||||||
|
throw new LogicException('Cannot call authenticate on this request, as it is not behind a firewall.');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->authenticatorManagers->get($firewallConfig->getName())->authenticate($token);
|
||||||
|
}
|
||||||
|
}
|
@ -40,14 +40,16 @@ class AuthenticatorManager implements AuthenticationManagerInterface
|
|||||||
private $authenticators;
|
private $authenticators;
|
||||||
private $eventDispatcher;
|
private $eventDispatcher;
|
||||||
private $eraseCredentials;
|
private $eraseCredentials;
|
||||||
|
private $providerKey;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param AuthenticatorInterface[] $authenticators The authenticators, with keys that match what's passed to AuthenticatorManagerListener
|
* @param AuthenticatorInterface[] $authenticators The authenticators, with keys that match what's passed to AuthenticatorManagerListener
|
||||||
*/
|
*/
|
||||||
public function __construct(iterable $authenticators, EventDispatcherInterface $eventDispatcher, bool $eraseCredentials = true)
|
public function __construct(iterable $authenticators, EventDispatcherInterface $eventDispatcher, string $providerKey, bool $eraseCredentials = true)
|
||||||
{
|
{
|
||||||
$this->authenticators = $authenticators;
|
$this->authenticators = $authenticators;
|
||||||
$this->eventDispatcher = $eventDispatcher;
|
$this->eventDispatcher = $eventDispatcher;
|
||||||
|
$this->providerKey = $providerKey;
|
||||||
$this->eraseCredentials = $eraseCredentials;
|
$this->eraseCredentials = $eraseCredentials;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ use Symfony\Component\Security\Http\Event\LoginSuccessEvent;
|
|||||||
*/
|
*/
|
||||||
class AuthenticatorManagerListener extends AbstractListener
|
class AuthenticatorManagerListener extends AbstractListener
|
||||||
{
|
{
|
||||||
private $authenticationManager;
|
private $authenticatorManager;
|
||||||
private $authenticatorHandler;
|
private $authenticatorHandler;
|
||||||
private $authenticators;
|
private $authenticators;
|
||||||
protected $providerKey;
|
protected $providerKey;
|
||||||
@ -45,7 +45,7 @@ class AuthenticatorManagerListener extends AbstractListener
|
|||||||
*/
|
*/
|
||||||
public function __construct(AuthenticationManagerInterface $authenticationManager, AuthenticatorHandler $authenticatorHandler, iterable $authenticators, string $providerKey, EventDispatcherInterface $eventDispatcher, ?LoggerInterface $logger = null)
|
public function __construct(AuthenticationManagerInterface $authenticationManager, AuthenticatorHandler $authenticatorHandler, iterable $authenticators, string $providerKey, EventDispatcherInterface $eventDispatcher, ?LoggerInterface $logger = null)
|
||||||
{
|
{
|
||||||
$this->authenticationManager = $authenticationManager;
|
$this->authenticatorManager = $authenticationManager;
|
||||||
$this->authenticatorHandler = $authenticatorHandler;
|
$this->authenticatorHandler = $authenticatorHandler;
|
||||||
$this->authenticators = $authenticators;
|
$this->authenticators = $authenticators;
|
||||||
$this->providerKey = $providerKey;
|
$this->providerKey = $providerKey;
|
||||||
@ -157,7 +157,7 @@ class AuthenticatorManagerListener extends AbstractListener
|
|||||||
}
|
}
|
||||||
// pass the token into the AuthenticationManager system
|
// pass the token into the AuthenticationManager system
|
||||||
// this indirectly calls AuthenticatorManager::authenticate()
|
// this indirectly calls AuthenticatorManager::authenticate()
|
||||||
$token = $this->authenticationManager->authenticate($token);
|
$token = $this->authenticatorManager->authenticate($token);
|
||||||
|
|
||||||
if (null !== $this->logger) {
|
if (null !== $this->logger) {
|
||||||
$this->logger->info('Authenticator successful!', ['token' => $token, 'authenticator' => \get_class($authenticator)]);
|
$this->logger->info('Authenticator successful!', ['token' => $token, 'authenticator' => \get_class($authenticator)]);
|
||||||
|
Reference in New Issue
Block a user