[BC break][SecurityBundle] Changed the way to register factories
This commit is contained in:
parent
ae1e9cbedf
commit
413756c103
@ -36,6 +36,9 @@ To get the diff between two versions, go to https://github.com/symfony/symfony/c
|
|||||||
|
|
||||||
### SecurityBundle
|
### SecurityBundle
|
||||||
|
|
||||||
|
* [BC BREAK] The custom factories for the firewall configuration are now registered during the build method of
|
||||||
|
bundles instead of being registered by the end-user.
|
||||||
|
|
||||||
* [BC BREAK] The Firewall listener is now registered after the Router one.
|
* [BC BREAK] The Firewall listener is now registered after the Router one.
|
||||||
It means that specific Firewall URLs (like /login_check and /logout must now have proper
|
It means that specific Firewall URLs (like /login_check and /logout must now have proper
|
||||||
route defined in your routing configuration)
|
route defined in your routing configuration)
|
||||||
|
@ -1,53 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of the Symfony framework.
|
|
||||||
*
|
|
||||||
* (c) Fabien Potencier <fabien@symfony.com>
|
|
||||||
*
|
|
||||||
* This source file is subject to the MIT license that is bundled
|
|
||||||
* with this source code in the file LICENSE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Symfony\Bundle\SecurityBundle\DependencyInjection;
|
|
||||||
|
|
||||||
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
|
|
||||||
use Symfony\Component\Config\Definition\ConfigurationInterface;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class contains the configuration information for the following tags:
|
|
||||||
*
|
|
||||||
* * security.config
|
|
||||||
* * security.acl
|
|
||||||
*
|
|
||||||
* This information is solely responsible for how the different configuration
|
|
||||||
* sections are normalized, and merged.
|
|
||||||
*
|
|
||||||
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
|
||||||
*/
|
|
||||||
class FactoryConfiguration implements ConfigurationInterface
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Generates the configuration tree builder.
|
|
||||||
*
|
|
||||||
* @return \Symfony\Component\Config\Definition\Builder\TreeBuilder The tree builder
|
|
||||||
*/
|
|
||||||
public function getConfigTreeBuilder()
|
|
||||||
{
|
|
||||||
$tb = new TreeBuilder();
|
|
||||||
|
|
||||||
$tb
|
|
||||||
->root('security')
|
|
||||||
->ignoreExtraKeys()
|
|
||||||
->fixXmlConfig('factory', 'factories')
|
|
||||||
->children()
|
|
||||||
->arrayNode('factories')
|
|
||||||
->prototype('scalar')->end()
|
|
||||||
->end()
|
|
||||||
->end()
|
|
||||||
->end()
|
|
||||||
;
|
|
||||||
|
|
||||||
return $tb;
|
|
||||||
}
|
|
||||||
}
|
|
@ -70,11 +70,6 @@ class MainConfiguration implements ConfigurationInterface
|
|||||||
->end()
|
->end()
|
||||||
->end()
|
->end()
|
||||||
->end()
|
->end()
|
||||||
// add a faux-entry for factories, so that no validation error is thrown
|
|
||||||
->fixXmlConfig('factory', 'factories')
|
|
||||||
->children()
|
|
||||||
->arrayNode('factories')->ignoreExtraKeys()->end()
|
|
||||||
->end()
|
|
||||||
;
|
;
|
||||||
|
|
||||||
$this->addAclSection($rootNode);
|
$this->addAclSection($rootNode);
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
namespace Symfony\Bundle\SecurityBundle\DependencyInjection;
|
namespace Symfony\Bundle\SecurityBundle\DependencyInjection;
|
||||||
|
|
||||||
|
use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\SecurityFactoryInterface;
|
||||||
use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\UserProvider\UserProviderFactoryInterface;
|
use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\UserProvider\UserProviderFactoryInterface;
|
||||||
use Symfony\Component\DependencyInjection\DefinitionDecorator;
|
use Symfony\Component\DependencyInjection\DefinitionDecorator;
|
||||||
use Symfony\Component\DependencyInjection\Alias;
|
use Symfony\Component\DependencyInjection\Alias;
|
||||||
@ -36,22 +37,24 @@ class SecurityExtension extends Extension
|
|||||||
private $requestMatchers = array();
|
private $requestMatchers = array();
|
||||||
private $contextListeners = array();
|
private $contextListeners = array();
|
||||||
private $listenerPositions = array('pre_auth', 'form', 'http', 'remember_me');
|
private $listenerPositions = array('pre_auth', 'form', 'http', 'remember_me');
|
||||||
private $factories;
|
private $factories = array();
|
||||||
private $userProviderFactories = array();
|
private $userProviderFactories = array();
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
foreach ($this->listenerPositions as $position) {
|
||||||
|
$this->factories[$position] = array();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function load(array $configs, ContainerBuilder $container)
|
public function load(array $configs, ContainerBuilder $container)
|
||||||
{
|
{
|
||||||
if (!array_filter($configs)) {
|
if (!array_filter($configs)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// first assemble the factories
|
|
||||||
$factoriesConfig = new FactoryConfiguration();
|
|
||||||
$config = $this->processConfiguration($factoriesConfig, $configs);
|
|
||||||
$factories = $this->createListenerFactories($container, $config);
|
|
||||||
|
|
||||||
// normalize and merge the actual configuration
|
// normalize and merge the actual configuration
|
||||||
$mainConfig = new MainConfiguration($factories, $this->userProviderFactories);
|
$mainConfig = new MainConfiguration($this->factories, $this->userProviderFactories);
|
||||||
$config = $this->processConfiguration($mainConfig, $configs);
|
$config = $this->processConfiguration($mainConfig, $configs);
|
||||||
|
|
||||||
// load services
|
// load services
|
||||||
@ -207,14 +210,11 @@ class SecurityExtension extends Extension
|
|||||||
$arguments[1] = $userProviders;
|
$arguments[1] = $userProviders;
|
||||||
$definition->setArguments($arguments);
|
$definition->setArguments($arguments);
|
||||||
|
|
||||||
// create security listener factories
|
|
||||||
$factories = $this->createListenerFactories($container, $config);
|
|
||||||
|
|
||||||
// load firewall map
|
// load firewall map
|
||||||
$mapDef = $container->getDefinition('security.firewall.map');
|
$mapDef = $container->getDefinition('security.firewall.map');
|
||||||
$map = $authenticationProviders = array();
|
$map = $authenticationProviders = array();
|
||||||
foreach ($firewalls as $name => $firewall) {
|
foreach ($firewalls as $name => $firewall) {
|
||||||
list($matcher, $listeners, $exceptionListener) = $this->createFirewall($container, $name, $firewall, $authenticationProviders, $providerIds, $factories);
|
list($matcher, $listeners, $exceptionListener) = $this->createFirewall($container, $name, $firewall, $authenticationProviders, $providerIds);
|
||||||
|
|
||||||
$contextId = 'security.firewall.map.context.'.$name;
|
$contextId = 'security.firewall.map.context.'.$name;
|
||||||
$context = $container->setDefinition($contextId, new DefinitionDecorator('security.firewall.context'));
|
$context = $container->setDefinition($contextId, new DefinitionDecorator('security.firewall.context'));
|
||||||
@ -236,7 +236,7 @@ class SecurityExtension extends Extension
|
|||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createFirewall(ContainerBuilder $container, $id, $firewall, &$authenticationProviders, $providerIds, array $factories)
|
private function createFirewall(ContainerBuilder $container, $id, $firewall, &$authenticationProviders, $providerIds)
|
||||||
{
|
{
|
||||||
// Matcher
|
// Matcher
|
||||||
$i = 0;
|
$i = 0;
|
||||||
@ -309,7 +309,7 @@ class SecurityExtension extends Extension
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Authentication listeners
|
// Authentication listeners
|
||||||
list($authListeners, $defaultEntryPoint) = $this->createAuthenticationListeners($container, $id, $firewall, $authenticationProviders, $defaultProvider, $factories);
|
list($authListeners, $defaultEntryPoint) = $this->createAuthenticationListeners($container, $id, $firewall, $authenticationProviders, $defaultProvider);
|
||||||
|
|
||||||
$listeners = array_merge($listeners, $authListeners);
|
$listeners = array_merge($listeners, $authListeners);
|
||||||
|
|
||||||
@ -345,14 +345,14 @@ class SecurityExtension extends Extension
|
|||||||
return $this->contextListeners[$contextKey] = $listenerId;
|
return $this->contextListeners[$contextKey] = $listenerId;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createAuthenticationListeners($container, $id, $firewall, &$authenticationProviders, $defaultProvider, array $factories)
|
private function createAuthenticationListeners($container, $id, $firewall, &$authenticationProviders, $defaultProvider)
|
||||||
{
|
{
|
||||||
$listeners = array();
|
$listeners = array();
|
||||||
$hasListeners = false;
|
$hasListeners = false;
|
||||||
$defaultEntryPoint = null;
|
$defaultEntryPoint = null;
|
||||||
|
|
||||||
foreach ($this->listenerPositions as $position) {
|
foreach ($this->listenerPositions as $position) {
|
||||||
foreach ($factories[$position] as $factory) {
|
foreach ($this->factories[$position] as $factory) {
|
||||||
$key = str_replace('-', '_', $factory->getKey());
|
$key = str_replace('-', '_', $factory->getKey());
|
||||||
|
|
||||||
if (isset($firewall[$key])) {
|
if (isset($firewall[$key])) {
|
||||||
@ -548,44 +548,9 @@ class SecurityExtension extends Extension
|
|||||||
return $this->requestMatchers[$id] = new Reference($id);
|
return $this->requestMatchers[$id] = new Reference($id);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createListenerFactories(ContainerBuilder $container, $config)
|
public function addSecurityListenerFactory(SecurityFactoryInterface $factory)
|
||||||
{
|
{
|
||||||
if (null !== $this->factories) {
|
$this->factories[$factory->getPosition()][] = $factory;
|
||||||
return $this->factories;
|
|
||||||
}
|
|
||||||
|
|
||||||
// load service templates
|
|
||||||
$c = new ContainerBuilder();
|
|
||||||
$parameterBag = $container->getParameterBag();
|
|
||||||
|
|
||||||
$locator = new FileLocator(__DIR__.'/../Resources/config');
|
|
||||||
$resolver = new LoaderResolver(array(
|
|
||||||
new XmlFileLoader($c, $locator),
|
|
||||||
new YamlFileLoader($c, $locator),
|
|
||||||
new PhpFileLoader($c, $locator),
|
|
||||||
));
|
|
||||||
$loader = new DelegatingLoader($resolver);
|
|
||||||
|
|
||||||
$loader->load('security_factories.xml');
|
|
||||||
|
|
||||||
// load user-created listener factories
|
|
||||||
foreach ($config['factories'] as $factory) {
|
|
||||||
$loader->load($parameterBag->resolveValue($factory));
|
|
||||||
}
|
|
||||||
|
|
||||||
$tags = $c->findTaggedServiceIds('security.listener.factory');
|
|
||||||
|
|
||||||
$factories = array();
|
|
||||||
foreach ($this->listenerPositions as $position) {
|
|
||||||
$factories[$position] = array();
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (array_keys($tags) as $tag) {
|
|
||||||
$factory = $c->get($tag);
|
|
||||||
$factories[$factory->getPosition()][] = $factory;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->factories = $factories;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function addUserProviderFactory(UserProviderFactoryInterface $factory)
|
public function addUserProviderFactory(UserProviderFactoryInterface $factory)
|
||||||
|
@ -14,6 +14,11 @@ namespace Symfony\Bundle\SecurityBundle;
|
|||||||
use Symfony\Component\HttpKernel\Bundle\Bundle;
|
use Symfony\Component\HttpKernel\Bundle\Bundle;
|
||||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||||
use Symfony\Bundle\SecurityBundle\DependencyInjection\Compiler\AddSecurityVotersPass;
|
use Symfony\Bundle\SecurityBundle\DependencyInjection\Compiler\AddSecurityVotersPass;
|
||||||
|
use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\FormLoginFactory;
|
||||||
|
use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\HttpBasicFactory;
|
||||||
|
use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\HttpDigestFactory;
|
||||||
|
use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\RememberMeFactory;
|
||||||
|
use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\X509Factory;
|
||||||
use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\UserProvider\InMemoryFactory;
|
use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\UserProvider\InMemoryFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -27,7 +32,14 @@ class SecurityBundle extends Bundle
|
|||||||
{
|
{
|
||||||
parent::build($container);
|
parent::build($container);
|
||||||
|
|
||||||
$container->getExtension('security')->addUserProviderFactory(new InMemoryFactory());
|
$extension = $container->getExtension('security');
|
||||||
|
$extension->addSecurityListenerFactory(new FormLoginFactory());
|
||||||
|
$extension->addSecurityListenerFactory(new HttpBasicFactory());
|
||||||
|
$extension->addSecurityListenerFactory(new HttpDigestFactory());
|
||||||
|
$extension->addSecurityListenerFactory(new RememberMeFactory());
|
||||||
|
$extension->addSecurityListenerFactory(new X509Factory());
|
||||||
|
|
||||||
|
$extension->addUserProviderFactory(new InMemoryFactory());
|
||||||
$container->addCompilerPass(new AddSecurityVotersPass());
|
$container->addCompilerPass(new AddSecurityVotersPass());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,25 +33,6 @@ class ConfigurationTest extends \PHPUnit_Framework_TestCase
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that the main tree is OK to be passed a factory or factories
|
|
||||||
* key, without throwing any validation errors.
|
|
||||||
*/
|
|
||||||
public function testMainConfigTreeWithFactories()
|
|
||||||
{
|
|
||||||
$config = array_merge(self::$minimalConfig, array(
|
|
||||||
'factory' => array('foo' => 'bar'),
|
|
||||||
'factories' => array('lorem' => 'ipsum'),
|
|
||||||
));
|
|
||||||
|
|
||||||
$processor = new Processor();
|
|
||||||
$configuration = new MainConfiguration(array(), array());
|
|
||||||
$config = $processor->processConfiguration($configuration, array($config));
|
|
||||||
|
|
||||||
$this->assertFalse(array_key_exists('factory', $config), 'The factory key is silently removed without an exception');
|
|
||||||
$this->assertEquals(array(), $config['factories'], 'The factories key is just an empty array');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @expectedException Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
|
* @expectedException Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
|
||||||
*/
|
*/
|
||||||
|
@ -14,7 +14,7 @@ namespace Symfony\Bundle\SecurityBundle\Tests\DependencyInjection;
|
|||||||
use Symfony\Component\DependencyInjection\Reference;
|
use Symfony\Component\DependencyInjection\Reference;
|
||||||
|
|
||||||
use Symfony\Component\DependencyInjection\Parameter;
|
use Symfony\Component\DependencyInjection\Parameter;
|
||||||
|
use Symfony\Bundle\SecurityBundle\SecurityBundle;
|
||||||
use Symfony\Bundle\SecurityBundle\DependencyInjection\SecurityExtension;
|
use Symfony\Bundle\SecurityBundle\DependencyInjection\SecurityExtension;
|
||||||
use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\UserProvider\InMemoryFactory;
|
use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\UserProvider\InMemoryFactory;
|
||||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||||
@ -169,8 +169,10 @@ abstract class SecurityExtensionTest extends \PHPUnit_Framework_TestCase
|
|||||||
{
|
{
|
||||||
$container = new ContainerBuilder();
|
$container = new ContainerBuilder();
|
||||||
$security = new SecurityExtension();
|
$security = new SecurityExtension();
|
||||||
$security->addUserProviderFactory(new InMemoryFactory());
|
|
||||||
$container->registerExtension($security);
|
$container->registerExtension($security);
|
||||||
|
|
||||||
|
$bundle = new SecurityBundle();
|
||||||
|
$bundle->build($container); // Attach all default factories
|
||||||
$this->loadFromFile($container, $file);
|
$this->loadFromFile($container, $file);
|
||||||
|
|
||||||
$container->getCompilerPassConfig()->setOptimizationPasses(array());
|
$container->getCompilerPassConfig()->setOptimizationPasses(array());
|
||||||
|
Reference in New Issue
Block a user