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\DependencyInjection\Alias;
|
||||
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
|
||||
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
|
||||
use Symfony\Component\DependencyInjection\ChildDefinition;
|
||||
use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
@ -278,19 +279,16 @@ class SecurityExtension extends Extension implements PrependExtensionInterface
|
||||
$mapDef->replaceArgument(0, ServiceLocatorTagPass::register($container, $contextRefs));
|
||||
$mapDef->replaceArgument(1, new IteratorArgument($map));
|
||||
|
||||
// add authentication providers to authentication manager
|
||||
$authenticationProviders = array_map(function ($id) {
|
||||
return new Reference($id);
|
||||
}, array_unique($authenticationProviders));
|
||||
$authenticationManagerId = 'security.authentication.manager.provider';
|
||||
if ($this->authenticatorManagerEnabled) {
|
||||
$authenticationManagerId = 'security.authentication.manager.authenticator';
|
||||
$container->setAlias('security.authentication.manager', new Alias($authenticationManagerId));
|
||||
if (!$this->authenticatorManagerEnabled) {
|
||||
// add authentication providers to authentication manager
|
||||
$authenticationProviders = array_map(function ($id) {
|
||||
return new Reference($id);
|
||||
}, array_unique($authenticationProviders));
|
||||
|
||||
$container
|
||||
->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
|
||||
if (!$customUserChecker) {
|
||||
@ -441,17 +439,28 @@ class SecurityExtension extends Extension implements PrependExtensionInterface
|
||||
$authenticationProviders = array_merge($authenticationProviders, $firewallAuthenticationProviders);
|
||||
|
||||
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
|
||||
$container
|
||||
->setDefinition('security.firewall.authenticator.'.$id.'.locator', new ChildDefinition('security.firewall.authenticator.locator'))
|
||||
->setArguments([array_map(function ($id) {
|
||||
return new Reference($id);
|
||||
}, $firewallAuthenticationProviders)])
|
||||
->setArguments([$authenticators])
|
||||
->addTag('container.service_locator')
|
||||
;
|
||||
|
||||
$container
|
||||
->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(3, $id)
|
||||
;
|
||||
|
@ -6,7 +6,10 @@
|
||||
<services>
|
||||
<!-- 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="service" id="event_dispatcher" />
|
||||
<argument>%security.authentication.manager.erase_credentials%</argument>
|
||||
@ -14,6 +17,18 @@
|
||||
<argument type="service" id="event_dispatcher" />
|
||||
</call>
|
||||
</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="security.authenticator_handler"
|
||||
@ -35,7 +50,7 @@
|
||||
class="Symfony\Bundle\SecurityBundle\EventListener\LazyAuthenticatorManagerListener"
|
||||
abstract="true">
|
||||
<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/> <!-- authenticator locator -->
|
||||
<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 $eventDispatcher;
|
||||
private $eraseCredentials;
|
||||
private $providerKey;
|
||||
|
||||
/**
|
||||
* @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->eventDispatcher = $eventDispatcher;
|
||||
$this->providerKey = $providerKey;
|
||||
$this->eraseCredentials = $eraseCredentials;
|
||||
}
|
||||
|
||||
|
@ -33,7 +33,7 @@ use Symfony\Component\Security\Http\Event\LoginSuccessEvent;
|
||||
*/
|
||||
class AuthenticatorManagerListener extends AbstractListener
|
||||
{
|
||||
private $authenticationManager;
|
||||
private $authenticatorManager;
|
||||
private $authenticatorHandler;
|
||||
private $authenticators;
|
||||
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)
|
||||
{
|
||||
$this->authenticationManager = $authenticationManager;
|
||||
$this->authenticatorManager = $authenticationManager;
|
||||
$this->authenticatorHandler = $authenticatorHandler;
|
||||
$this->authenticators = $authenticators;
|
||||
$this->providerKey = $providerKey;
|
||||
@ -157,7 +157,7 @@ class AuthenticatorManagerListener extends AbstractListener
|
||||
}
|
||||
// pass the token into the AuthenticationManager system
|
||||
// this indirectly calls AuthenticatorManager::authenticate()
|
||||
$token = $this->authenticationManager->authenticate($token);
|
||||
$token = $this->authenticatorManager->authenticate($token);
|
||||
|
||||
if (null !== $this->logger) {
|
||||
$this->logger->info('Authenticator successful!', ['token' => $token, 'authenticator' => \get_class($authenticator)]);
|
||||
|
Reference in New Issue
Block a user