Преглед изворни кода

[Security] added AbstractFactory

Lukas Kahwe Smith пре 14 година
родитељ
комит
2539da5e6a

+ 171 - 0
src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/AbstractFactory.php

@@ -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;
+    }
+}

+ 31 - 58
src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/FormLoginFactory.php

@@ -19,63 +19,46 @@ use Symfony\Component\DependencyInjection\Reference;
  * FormLoginFactory creates services for form login authentication.
  *
  * @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()
+    {
+        $this->addOption('username_parameter', '_username');
+        $this->addOption('password_parameter', '_password');
+        $this->addOption('post_only', true);
+    }
+
+    public function getPosition()
+    {
+        return 'form';
+    }
+
+    public function getKey()
+    {
+        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($userProvider))
+            ->setArgument(0, new Reference($userProviderId))
             ->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']));
-        }
+        return $provider;
+    }
 
-        // form entry point
+    protected function createEntryPoint($container, $id, $options, $defaultEntryPoint)
+    {
         $entryPointId = 'security.authentication.form_entry_point.'.$id;
         $container
             ->setDefinition($entryPointId, new DefinitionDecorator('security.authentication.form_entry_point'))
@@ -83,16 +66,6 @@ class FormLoginFactory implements SecurityFactoryInterface
             ->addArgument($options['use_forward'])
         ;
 
-        return array($provider, $listenerId, $entryPointId);
-    }
-
-    public function getPosition()
-    {
-        return 'form';
-    }
-
-    public function getKey()
-    {
-        return 'form-login';
+        return $entryPointId;
     }
 }

+ 4 - 1
src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/SecurityExtensionTest.php

@@ -43,6 +43,9 @@ abstract class SecurityExtensionTest extends \PHPUnit_Framework_TestCase
             'security.authentication.provider.doctrine',
             'security.authentication.provider.service',
             'security.authentication.provider.anonymous',
+            'security.authentication.provider.dao',
+            'security.authentication.provider.pre_authenticated',
+            'security.authentication.provider.rememberme',
         );
 
         $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) {
             $contextDef = $container->getDefinition($contextId);
             $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(