[Security] added AbstractFactory
This commit is contained in:
parent
3ac4994507
commit
2539da5e6a
@ -0,0 +1,171 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien.potencier@symfony-project.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\DependencyInjection\DefinitionDecorator;
|
||||||
|
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||||
|
use Symfony\Component\DependencyInjection\Reference;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AbstractFactory is the base class for all classes inheriting from
|
||||||
|
* AbstractAuthenticationListener
|
||||||
|
*
|
||||||
|
* @author Lukas Kahwe Smith <smith@pooteeweet.org>
|
||||||
|
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
||||||
|
*/
|
||||||
|
abstract class AbstractFactory implements SecurityFactoryInterface
|
||||||
|
{
|
||||||
|
protected $options = array(
|
||||||
|
'check_path' => '/login_check',
|
||||||
|
'login_path' => '/login',
|
||||||
|
'use_forward' => false,
|
||||||
|
'always_use_default_target_path' => false,
|
||||||
|
'default_target_path' => '/',
|
||||||
|
'target_path_parameter' => '_target_path',
|
||||||
|
'use_referer' => false,
|
||||||
|
'failure_path' => null,
|
||||||
|
'failure_forward' => false,
|
||||||
|
);
|
||||||
|
|
||||||
|
public function create(ContainerBuilder $container, $id, $config, $userProviderId, $defaultEntryPointId)
|
||||||
|
{
|
||||||
|
if (!is_array($config)) {
|
||||||
|
$config = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
// merge set options with default options
|
||||||
|
$options = $this->getOptionsFromConfig($config);
|
||||||
|
|
||||||
|
// authentication provider
|
||||||
|
$authProviderId = $this->createAuthProvider($container, $id, $options, $userProviderId);
|
||||||
|
$container
|
||||||
|
->getDefinition($authProviderId)
|
||||||
|
->addTag('security.authentication_provider')
|
||||||
|
;
|
||||||
|
|
||||||
|
// authentication listener
|
||||||
|
$listenerId = $this->createListener($container, $id, $options, $userProviderId);
|
||||||
|
|
||||||
|
// add remember-me aware tag if requested
|
||||||
|
if ($this->isRememberMeAware($config)) {
|
||||||
|
$container
|
||||||
|
->getDefinition($listenerId)
|
||||||
|
->addTag('security.remember_me_aware', array('id' => $id, 'provider' => $userProviderId))
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create entry point if applicable (optional)
|
||||||
|
$entryPointId = $this->createEntryPoint($container, $id, $options, $defaultEntryPointId);
|
||||||
|
|
||||||
|
return array($authProviderId, $listenerId, $entryPointId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final function addOption($name, $default = null)
|
||||||
|
{
|
||||||
|
$this->options[$name] = $default;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subclasses must return the id of a service which implements the
|
||||||
|
* AuthenticationProviderInterface.
|
||||||
|
*
|
||||||
|
* @param ContainerBuilder $container
|
||||||
|
* @param string $id The unique id of the firewall
|
||||||
|
* @param array $options The options array for this listener
|
||||||
|
* @param string $userProviderId The id of the user provider
|
||||||
|
*
|
||||||
|
* @return string never null, the id of the authentication provider
|
||||||
|
*/
|
||||||
|
abstract protected function createAuthProvider(ContainerBuilder $container, $id, $options, $userProviderId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subclasses must return the id of the abstract listener template.
|
||||||
|
*
|
||||||
|
* Listener definitions should inherit from the AbstractAuthenticationListener
|
||||||
|
* like this:
|
||||||
|
*
|
||||||
|
* <service id="my.listener.id"
|
||||||
|
* class="My\Concrete\Classname"
|
||||||
|
* parent="security.authentication.listener.abstract"
|
||||||
|
* abstract="true" />
|
||||||
|
*
|
||||||
|
* In the above case, this method would return "my.listener.id".
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
abstract protected function getListenerId();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subclasses may create an entry point of their as they see fit. The
|
||||||
|
* default implementation does not change the default entry point.
|
||||||
|
*
|
||||||
|
* @param ContainerBuilder $container
|
||||||
|
* @param string $id
|
||||||
|
* @param array $options
|
||||||
|
* @param string $defaultEntryPointId
|
||||||
|
*
|
||||||
|
* @return string the entry point id
|
||||||
|
*/
|
||||||
|
protected function createEntryPoint($container, $id, $options, $defaultEntryPointId)
|
||||||
|
{
|
||||||
|
return $defaultEntryPointId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subclasses may disable remember-me features for the listener, by
|
||||||
|
* always returning false from this method.
|
||||||
|
*
|
||||||
|
* @param array $config
|
||||||
|
*
|
||||||
|
* @return Boolean Whether a possibly configured RememberMeServices should be set for this listener
|
||||||
|
*/
|
||||||
|
protected function isRememberMeAware($config)
|
||||||
|
{
|
||||||
|
return !isset($config['remember_me']) || (Boolean) $config['remember_me'];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function createListener($container, $id, $options, $userProvider)
|
||||||
|
{
|
||||||
|
$listenerId = $this->getListenerId();
|
||||||
|
$listener = new DefinitionDecorator($listenerId);
|
||||||
|
$listener->setArgument(3, $id);
|
||||||
|
$listener->setArgument(4, $options);
|
||||||
|
|
||||||
|
// success handler
|
||||||
|
if (isset($config['success_handler'])) {
|
||||||
|
$listener->setArgument(5, new Reference($config['success_handler']));
|
||||||
|
}
|
||||||
|
|
||||||
|
// failure handler
|
||||||
|
if (isset($config['failure_handler'])) {
|
||||||
|
$listener->setArgument(6, new Reference($config['failure_handler']));
|
||||||
|
}
|
||||||
|
|
||||||
|
$listenerId .= '.'.$id;
|
||||||
|
$container->setDefinition($listenerId, $listener);
|
||||||
|
|
||||||
|
return $listenerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final function getOptionsFromConfig($config)
|
||||||
|
{
|
||||||
|
$options = $this->options;
|
||||||
|
|
||||||
|
foreach (array_keys($options) as $key) {
|
||||||
|
if (array_key_exists($key, $config)) {
|
||||||
|
$options[$key] = $config[$key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $options;
|
||||||
|
}
|
||||||
|
}
|
@ -19,71 +19,15 @@ use Symfony\Component\DependencyInjection\Reference;
|
|||||||
* FormLoginFactory creates services for form login authentication.
|
* FormLoginFactory creates services for form login authentication.
|
||||||
*
|
*
|
||||||
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
|
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||||
|
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
||||||
*/
|
*/
|
||||||
class FormLoginFactory implements SecurityFactoryInterface
|
class FormLoginFactory extends AbstractFactory
|
||||||
{
|
{
|
||||||
public function create(ContainerBuilder $container, $id, $config, $userProvider, $defaultEntryPoint)
|
public function __construct()
|
||||||
{
|
{
|
||||||
$provider = 'security.authentication.provider.dao.'.$id;
|
$this->addOption('username_parameter', '_username');
|
||||||
$container
|
$this->addOption('password_parameter', '_password');
|
||||||
->setDefinition($provider, new DefinitionDecorator('security.authentication.provider.dao'))
|
$this->addOption('post_only', true);
|
||||||
->setArgument(0, new Reference($userProvider))
|
|
||||||
->setArgument(2, $id)
|
|
||||||
->addTag('security.authentication_provider')
|
|
||||||
;
|
|
||||||
|
|
||||||
// listener
|
|
||||||
$listenerId = 'security.authentication.listener.form.'.$id;
|
|
||||||
$listener = $container->setDefinition($listenerId, new DefinitionDecorator('security.authentication.listener.form'));
|
|
||||||
$listener->setArgument(3, $id);
|
|
||||||
|
|
||||||
// add remember-me tag
|
|
||||||
$rememberMe = true;
|
|
||||||
if (isset($config['remember_me']) && false === $config['remember_me']) {
|
|
||||||
$rememberMe = false;
|
|
||||||
}
|
|
||||||
if ($rememberMe) {
|
|
||||||
$listener->addTag('security.remember_me_aware', array('id' => $id, 'provider' => $userProvider));
|
|
||||||
}
|
|
||||||
|
|
||||||
// generate options
|
|
||||||
$options = array(
|
|
||||||
'check_path' => '/login_check',
|
|
||||||
'login_path' => '/login',
|
|
||||||
'use_forward' => false,
|
|
||||||
'always_use_default_target_path' => false,
|
|
||||||
'default_target_path' => '/',
|
|
||||||
'target_path_parameter' => '_target_path',
|
|
||||||
'use_referer' => false,
|
|
||||||
'failure_path' => null,
|
|
||||||
'failure_forward' => false,
|
|
||||||
);
|
|
||||||
foreach (array_keys($options) as $key) {
|
|
||||||
if (array_key_exists($key, $config)) {
|
|
||||||
$options[$key] = $config[$key];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$listener->setArgument(4, $options);
|
|
||||||
|
|
||||||
// success handler
|
|
||||||
if (isset($config['success_handler'])) {
|
|
||||||
$listener->setArgument(5, new Reference($config['success_handler']));
|
|
||||||
}
|
|
||||||
|
|
||||||
// failure handler
|
|
||||||
if (isset($config['failure_handler'])) {
|
|
||||||
$listener->setArgument(6, new Reference($config['failure_handler']));
|
|
||||||
}
|
|
||||||
|
|
||||||
// form entry point
|
|
||||||
$entryPointId = 'security.authentication.form_entry_point.'.$id;
|
|
||||||
$container
|
|
||||||
->setDefinition($entryPointId, new DefinitionDecorator('security.authentication.form_entry_point'))
|
|
||||||
->addArgument($options['login_path'])
|
|
||||||
->addArgument($options['use_forward'])
|
|
||||||
;
|
|
||||||
|
|
||||||
return array($provider, $listenerId, $entryPointId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getPosition()
|
public function getPosition()
|
||||||
@ -95,4 +39,33 @@ class FormLoginFactory implements SecurityFactoryInterface
|
|||||||
{
|
{
|
||||||
return 'form-login';
|
return 'form-login';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function getListenerId()
|
||||||
|
{
|
||||||
|
return 'security.authentication.listener.form';
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function createAuthProvider(ContainerBuilder $container, $id, $options, $userProviderId)
|
||||||
|
{
|
||||||
|
$provider = 'security.authentication.provider.dao.'.$id;
|
||||||
|
$container
|
||||||
|
->setDefinition($provider, new DefinitionDecorator('security.authentication.provider.dao'))
|
||||||
|
->setArgument(0, new Reference($userProviderId))
|
||||||
|
->setArgument(2, $id)
|
||||||
|
;
|
||||||
|
|
||||||
|
return $provider;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function createEntryPoint($container, $id, $options, $defaultEntryPoint)
|
||||||
|
{
|
||||||
|
$entryPointId = 'security.authentication.form_entry_point.'.$id;
|
||||||
|
$container
|
||||||
|
->setDefinition($entryPointId, new DefinitionDecorator('security.authentication.form_entry_point'))
|
||||||
|
->addArgument($options['login_path'])
|
||||||
|
->addArgument($options['use_forward'])
|
||||||
|
;
|
||||||
|
|
||||||
|
return $entryPointId;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,6 +43,9 @@ abstract class SecurityExtensionTest extends \PHPUnit_Framework_TestCase
|
|||||||
'security.authentication.provider.doctrine',
|
'security.authentication.provider.doctrine',
|
||||||
'security.authentication.provider.service',
|
'security.authentication.provider.service',
|
||||||
'security.authentication.provider.anonymous',
|
'security.authentication.provider.anonymous',
|
||||||
|
'security.authentication.provider.dao',
|
||||||
|
'security.authentication.provider.pre_authenticated',
|
||||||
|
'security.authentication.provider.rememberme',
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->assertEquals(array(), array_diff($expectedProviders, $providers));
|
$this->assertEquals(array(), array_diff($expectedProviders, $providers));
|
||||||
@ -58,7 +61,7 @@ abstract class SecurityExtensionTest extends \PHPUnit_Framework_TestCase
|
|||||||
foreach (array_keys($arguments[1]) as $contextId) {
|
foreach (array_keys($arguments[1]) as $contextId) {
|
||||||
$contextDef = $container->getDefinition($contextId);
|
$contextDef = $container->getDefinition($contextId);
|
||||||
$arguments = $contextDef->getArguments();
|
$arguments = $contextDef->getArguments();
|
||||||
$listeners[] = array_map(function ($ref) { return preg_replace('/\.[a-f0-9]+$/', '', (string) $ref); }, $arguments[0]);
|
$listeners[] = array_map(function ($ref) { return preg_replace('/\.[a-f0-9]+$/', '', (string) $ref); }, $arguments['index_0']);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->assertEquals(array(
|
$this->assertEquals(array(
|
||||||
|
Reference in New Issue
Block a user