feature #33503 [SecurityBundle] Move Anonymous DI integration to new AnonymousFactory (wouterj)

This PR was merged into the 4.4 branch.

Discussion
----------

[SecurityBundle] Move Anonymous DI integration to new AnonymousFactory

| Q             | A
| ------------- | ---
| Branch?       | 4.4
| Bug fix?      | no
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | -
| License       | MIT
| Doc PR        | n/a

For some reason, all security authentication providers/listeners have a `SecurityFactory` that adds configuration and registers the necessary services, except from anonymous security. I'm not sure why that has not been done. The only thing I can think of is making sure it is added to the end.

I've added a new "internal" factory position, to make sure it is always the last registered provider and moved everything to a new `AnonymousFactory`.

Nothing changes on the usage side, but it makes internal code a bit easier to understand and makes sure we don't break anything while refactoring the `SecurityExtension` in the future.

Commits
-------

0da2761c15 Move Anonymous config to a SecurityFactory
This commit is contained in:
Fabien Potencier 2019-09-11 06:57:59 +02:00
commit 419be6a6e5
4 changed files with 66 additions and 36 deletions

View File

@ -255,12 +255,6 @@ class MainConfiguration implements ConfigurationInterface
->end()
->end()
->end()
->arrayNode('anonymous')
->canBeUnset()
->children()
->scalarNode('secret')->defaultNull()->end()
->end()
->end()
->arrayNode('switch_user')
->canBeUnset()
->children()

View File

@ -0,0 +1,63 @@
<?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\DependencyInjection\Security\Factory;
use Symfony\Component\Config\Definition\Builder\NodeDefinition;
use Symfony\Component\DependencyInjection\ChildDefinition;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Parameter;
/**
* @author Wouter de Jong <wouter@wouterj.nl>
*/
class AnonymousFactory implements SecurityFactoryInterface
{
public function create(ContainerBuilder $container, $id, $config, $userProvider, $defaultEntryPoint)
{
if (null === $config['secret']) {
$firewall['anonymous']['secret'] = new Parameter('container.build_hash');
}
$listenerId = 'security.authentication.listener.anonymous.'.$id;
$container
->setDefinition($listenerId, new ChildDefinition('security.authentication.listener.anonymous'))
->replaceArgument(1, $firewall['anonymous']['secret'])
;
$providerId = 'security.authentication.provider.anonymous.'.$id;
$container
->setDefinition($providerId, new ChildDefinition('security.authentication.provider.anonymous'))
->replaceArgument(0, $firewall['anonymous']['secret'])
;
return [$providerId, $listenerId, $defaultEntryPoint];
}
public function getPosition()
{
return 'anonymous';
}
public function getKey()
{
return 'anonymous';
}
public function addConfiguration(NodeDefinition $builder)
{
$builder
->children()
->scalarNode('secret')->defaultNull()->end()
->end()
;
}
}

View File

@ -25,7 +25,6 @@ use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
use Symfony\Component\DependencyInjection\Parameter;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
@ -48,7 +47,7 @@ class SecurityExtension extends Extension implements PrependExtensionInterface
private $requestMatchers = [];
private $expressions = [];
private $contextListeners = [];
private $listenerPositions = ['pre_auth', 'form', 'http', 'remember_me'];
private $listenerPositions = ['pre_auth', 'form', 'http', 'remember_me', 'anonymous'];
private $factories = [];
private $userProviderFactories = [];
private $statelessFirewallKeys = [];
@ -429,10 +428,6 @@ class SecurityExtension extends Extension implements PrependExtensionInterface
}
}
if (isset($firewall['anonymous'])) {
$listenerKeys[] = 'anonymous';
}
$config->replaceArgument(10, $listenerKeys);
$config->replaceArgument(11, isset($firewall['switch_user']) ? $firewall['switch_user'] : null);
@ -488,30 +483,6 @@ class SecurityExtension extends Extension implements PrependExtensionInterface
}
}
// Anonymous
if (isset($firewall['anonymous'])) {
if (null === $firewall['anonymous']['secret']) {
$firewall['anonymous']['secret'] = new Parameter('container.build_hash');
}
$listenerId = 'security.authentication.listener.anonymous.'.$id;
$container
->setDefinition($listenerId, new ChildDefinition('security.authentication.listener.anonymous'))
->replaceArgument(1, $firewall['anonymous']['secret'])
;
$listeners[] = new Reference($listenerId);
$providerId = 'security.authentication.provider.anonymous.'.$id;
$container
->setDefinition($providerId, new ChildDefinition('security.authentication.provider.anonymous'))
->replaceArgument(0, $firewall['anonymous']['secret'])
;
$authenticationProviders[] = $providerId;
$hasListeners = true;
}
if (false === $hasListeners) {
throw new InvalidConfigurationException(sprintf('No authentication listener registered for firewall "%s".', $id));
}

View File

@ -15,6 +15,7 @@ use Symfony\Bundle\SecurityBundle\DependencyInjection\Compiler\AddExpressionLang
use Symfony\Bundle\SecurityBundle\DependencyInjection\Compiler\AddSecurityVotersPass;
use Symfony\Bundle\SecurityBundle\DependencyInjection\Compiler\AddSessionDomainConstraintPass;
use Symfony\Bundle\SecurityBundle\DependencyInjection\Compiler\RegisterCsrfTokenClearingLogoutHandlerPass;
use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\AnonymousFactory;
use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\FormLoginFactory;
use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\FormLoginLdapFactory;
use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\GuardAuthenticationFactory;
@ -57,6 +58,7 @@ class SecurityBundle extends Bundle
$extension->addSecurityListenerFactory(new SimplePreAuthenticationFactory(false));
$extension->addSecurityListenerFactory(new SimpleFormFactory(false));
$extension->addSecurityListenerFactory(new GuardAuthenticationFactory());
$extension->addSecurityListenerFactory(new AnonymousFactory());
$extension->addUserProviderFactory(new InMemoryFactory());
$extension->addUserProviderFactory(new LdapFactory());