Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit b056d40

Browse files
committed
feature #21450 [Security] Lazy load guard authenticators and authentication providers (chalasr)
This PR was squashed before being merged into the 3.3-dev branch (closes #21450). Discussion ---------- [Security] Lazy load guard authenticators and authentication providers | Q | A | ------------- | --- | Branch? | master | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | n/a | License | MIT | Doc PR | n/a Authentication stops on the first authenticator that fails or succeeds, let's instantiate them only if actually needed. Commits ------- cd6422a [SecurityBundle] Lazy load authentication providers b8a23de [Security][Guard] Lazy load authenticators
2 parents 7c9a5c1 + cd6422a commit b056d40

File tree

8 files changed

+38
-29
lines changed

8 files changed

+38
-29
lines changed

src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/GuardAuthenticationFactory.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory;
1313

1414
use Symfony\Component\Config\Definition\Builder\NodeDefinition;
15+
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
1516
use Symfony\Component\DependencyInjection\ChildDefinition;
1617
use Symfony\Component\DependencyInjection\ContainerBuilder;
1718
use Symfony\Component\DependencyInjection\Reference;
@@ -62,11 +63,13 @@ public function create(ContainerBuilder $container, $id, $config, $userProvider,
6263
$authenticatorReferences[] = new Reference($authenticatorId);
6364
}
6465

66+
$authenticators = new IteratorArgument($authenticatorReferences);
67+
6568
// configure the GuardAuthenticationFactory to have the dynamic constructor arguments
6669
$providerId = 'security.authentication.provider.guard.'.$id;
6770
$container
6871
->setDefinition($providerId, new ChildDefinition('security.authentication.provider.guard'))
69-
->replaceArgument(0, $authenticatorReferences)
72+
->replaceArgument(0, $authenticators)
7073
->replaceArgument(1, new Reference($userProvider))
7174
->replaceArgument(2, $id)
7275
->replaceArgument(3, new Reference('security.user_checker.'.$id))
@@ -76,7 +79,7 @@ public function create(ContainerBuilder $container, $id, $config, $userProvider,
7679
$listenerId = 'security.authentication.listener.guard.'.$id;
7780
$listener = $container->setDefinition($listenerId, new ChildDefinition('security.authentication.listener.guard'));
7881
$listener->replaceArgument(2, $id);
79-
$listener->replaceArgument(3, $authenticatorReferences);
82+
$listener->replaceArgument(3, $authenticators);
8083

8184
// determine the entryPointId to use
8285
$entryPointId = $this->determineEntryPoint($defaultEntryPoint, $config);

src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ private function createFirewalls($config, ContainerBuilder $container)
266266
}, array_values(array_unique($authenticationProviders)));
267267
$container
268268
->getDefinition('security.authentication.manager')
269-
->replaceArgument(0, $authenticationProviders)
269+
->replaceArgument(0, new IteratorArgument($authenticationProviders))
270270
;
271271
}
272272

src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727

2828
<!-- Authentication related services -->
2929
<service id="security.authentication.manager" class="Symfony\Component\Security\Core\Authentication\AuthenticationProviderManager" public="false">
30-
<argument type="collection" />
30+
<argument /> <!-- providers -->
3131
<argument>%security.authentication.manager.erase_credentials%</argument>
3232
<call method="setEventDispatcher">
3333
<argument type="service" id="event_dispatcher" />

src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Security/Factory/GuardAuthenticationFactoryTest.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\GuardAuthenticationFactory;
1515
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
16+
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
1617
use Symfony\Component\DependencyInjection\ContainerBuilder;
1718
use Symfony\Component\DependencyInjection\Reference;
1819

@@ -106,15 +107,15 @@ public function testBasicCreate()
106107

107108
$providerDefinition = $container->getDefinition('security.authentication.provider.guard.my_firewall');
108109
$this->assertEquals(array(
109-
'index_0' => array(new Reference('authenticator123')),
110+
'index_0' => new IteratorArgument(array(new Reference('authenticator123'))),
110111
'index_1' => new Reference('my_user_provider'),
111112
'index_2' => 'my_firewall',
112113
'index_3' => new Reference('security.user_checker.my_firewall'),
113114
), $providerDefinition->getArguments());
114115

115116
$listenerDefinition = $container->getDefinition('security.authentication.listener.guard.my_firewall');
116117
$this->assertEquals('my_firewall', $listenerDefinition->getArgument(2));
117-
$this->assertEquals(array(new Reference('authenticator123')), $listenerDefinition->getArgument(3));
118+
$this->assertEquals(array(new Reference('authenticator123')), $listenerDefinition->getArgument(3)->getValues());
118119
}
119120

120121
public function testExistingDefaultEntryPointUsed()

src/Symfony/Component/Security/Core/Authentication/AuthenticationProviderManager.php

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -37,23 +37,17 @@ class AuthenticationProviderManager implements AuthenticationManagerInterface
3737
/**
3838
* Constructor.
3939
*
40-
* @param AuthenticationProviderInterface[] $providers An array of AuthenticationProviderInterface instances
41-
* @param bool $eraseCredentials Whether to erase credentials after authentication or not
40+
* @param iterable|AuthenticationProviderInterface[] $providers An iterable with AuthenticationProviderInterface instances as values
41+
* @param bool $eraseCredentials Whether to erase credentials after authentication or not
4242
*
4343
* @throws \InvalidArgumentException
4444
*/
45-
public function __construct(array $providers, $eraseCredentials = true)
45+
public function __construct($providers, $eraseCredentials = true)
4646
{
4747
if (!$providers) {
4848
throw new \InvalidArgumentException('You must at least add one authentication provider.');
4949
}
5050

51-
foreach ($providers as $provider) {
52-
if (!$provider instanceof AuthenticationProviderInterface) {
53-
throw new \InvalidArgumentException(sprintf('Provider "%s" must implement the AuthenticationProviderInterface.', get_class($provider)));
54-
}
55-
}
56-
5751
$this->providers = $providers;
5852
$this->eraseCredentials = (bool) $eraseCredentials;
5953
}
@@ -72,6 +66,10 @@ public function authenticate(TokenInterface $token)
7266
$result = null;
7367

7468
foreach ($this->providers as $provider) {
69+
if (!$provider instanceof AuthenticationProviderInterface) {
70+
throw new \InvalidArgumentException(sprintf('Provider "%s" must implement the AuthenticationProviderInterface.', get_class($provider)));
71+
}
72+
7573
if (!$provider->supports($token)) {
7674
continue;
7775
}

src/Symfony/Component/Security/Core/Tests/Authentication/AuthenticationProviderManagerTest.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Symfony\Component\Security\Core\Exception\ProviderNotFoundException;
1616
use Symfony\Component\Security\Core\Exception\AuthenticationException;
1717
use Symfony\Component\Security\Core\Exception\AccountStatusException;
18+
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
1819
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
1920

2021
class AuthenticationProviderManagerTest extends \PHPUnit_Framework_TestCase
@@ -32,9 +33,9 @@ public function testAuthenticateWithoutProviders()
3233
*/
3334
public function testAuthenticateWithProvidersWithIncorrectInterface()
3435
{
35-
new AuthenticationProviderManager(array(
36+
(new AuthenticationProviderManager(array(
3637
new \stdClass(),
37-
));
38+
)))->authenticate($this->getMockBuilder(TokenInterface::class)->getMock());
3839
}
3940

4041
public function testAuthenticateWhenNoProviderSupportsToken()

src/Symfony/Component/Security/Guard/Firewall/GuardAuthenticationListener.php

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,13 @@ class GuardAuthenticationListener implements ListenerInterface
3939
private $rememberMeServices;
4040

4141
/**
42-
* @param GuardAuthenticatorHandler $guardHandler The Guard handler
43-
* @param AuthenticationManagerInterface $authenticationManager An AuthenticationManagerInterface instance
44-
* @param string $providerKey The provider (i.e. firewall) key
45-
* @param GuardAuthenticatorInterface[] $guardAuthenticators The authenticators, with keys that match what's passed to GuardAuthenticationProvider
46-
* @param LoggerInterface $logger A LoggerInterface instance
42+
* @param GuardAuthenticatorHandler $guardHandler The Guard handler
43+
* @param AuthenticationManagerInterface $authenticationManager An AuthenticationManagerInterface instance
44+
* @param string $providerKey The provider (i.e. firewall) key
45+
* @param iterable|GuardAuthenticatorInterface[] $guardAuthenticators The authenticators, with keys that match what's passed to GuardAuthenticationProvider
46+
* @param LoggerInterface $logger A LoggerInterface instance
4747
*/
48-
public function __construct(GuardAuthenticatorHandler $guardHandler, AuthenticationManagerInterface $authenticationManager, $providerKey, array $guardAuthenticators, LoggerInterface $logger = null)
48+
public function __construct(GuardAuthenticatorHandler $guardHandler, AuthenticationManagerInterface $authenticationManager, $providerKey, $guardAuthenticators, LoggerInterface $logger = null)
4949
{
5050
if (empty($providerKey)) {
5151
throw new \InvalidArgumentException('$providerKey must not be empty.');
@@ -66,7 +66,13 @@ public function __construct(GuardAuthenticatorHandler $guardHandler, Authenticat
6666
public function handle(GetResponseEvent $event)
6767
{
6868
if (null !== $this->logger) {
69-
$this->logger->debug('Checking for guard authentication credentials.', array('firewall_key' => $this->providerKey, 'authenticators' => count($this->guardAuthenticators)));
69+
$context = array('firewall_key' => $this->providerKey);
70+
71+
if ($this->guardAuthenticators instanceof \Countable || is_array($this->guardAuthenticators)) {
72+
$context['authenticators'] = count($this->guardAuthenticators);
73+
}
74+
75+
$this->logger->debug('Checking for guard authentication credentials.', $context);
7076
}
7177

7278
foreach ($this->guardAuthenticators as $key => $guardAuthenticator) {

src/Symfony/Component/Security/Guard/Provider/GuardAuthenticationProvider.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,12 @@ class GuardAuthenticationProvider implements AuthenticationProviderInterface
4040
private $userChecker;
4141

4242
/**
43-
* @param GuardAuthenticatorInterface[] $guardAuthenticators The authenticators, with keys that match what's passed to GuardAuthenticationListener
44-
* @param UserProviderInterface $userProvider The user provider
45-
* @param string $providerKey The provider (i.e. firewall) key
46-
* @param UserCheckerInterface $userChecker
43+
* @param iterable|GuardAuthenticatorInterface[] $guardAuthenticators The authenticators, with keys that match what's passed to GuardAuthenticationListener
44+
* @param UserProviderInterface $userProvider The user provider
45+
* @param string $providerKey The provider (i.e. firewall) key
46+
* @param UserCheckerInterface $userChecker
4747
*/
48-
public function __construct(array $guardAuthenticators, UserProviderInterface $userProvider, $providerKey, UserCheckerInterface $userChecker)
48+
public function __construct($guardAuthenticators, UserProviderInterface $userProvider, $providerKey, UserCheckerInterface $userChecker)
4949
{
5050
$this->guardAuthenticators = $guardAuthenticators;
5151
$this->userProvider = $userProvider;

0 commit comments

Comments
 (0)