ソースを参照

Merge remote branch 'schmittjoh/security'

* schmittjoh/security:
  [HttpFoundation] added unit test
  [Security][HttpFoundation] splits Request::hasSession() into hasSession(), and hasPreviousSession()
  [SecurityBundle] added some tests
  add provider to configuration
  update DI to handle change in config and another provider
  separate dbal specific acl config
  add provider to configuration
  update DI to handle change in config and another provider
  separate dbal specific acl config
Fabien Potencier 14 年 前
コミット
50c1cce014

+ 4 - 0
UPDATE.md

@@ -123,6 +123,10 @@ beta1 to beta2
           'allow_add' => true,
           'allow_delete' => true,
       ));
+      
+* Request::hasSession() has been renamed to Request::hasPreviousSession(). The
+  method hasSession() still exists, but only checks if the request contains a
+  session object, not if the session was started in a previous request.
 
 * Serializer: The NormalizerInterface's `supports()` method has been split in
   two methods: `supportsNormalization` and `supportsDenormalization`.

+ 1 - 1
src/Symfony/Bundle/FrameworkBundle/RequestListener.php

@@ -67,7 +67,7 @@ class RequestListener
         }
 
         // starts the session if a session cookie already exists in the request...
-        if ($request->hasSession()) {
+        if ($request->hasPreviousSession()) {
             $request->getSession()->start();
         }
     }

+ 1 - 0
src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php

@@ -86,6 +86,7 @@ class MainConfiguration implements ConfigurationInterface
                                 ->scalarNode('prefix')->defaultValue('sf2_acl_')->end()
                             ->end()
                         ->end()
+                        ->scalarNode('provider')->end()
                         ->arrayNode('tables')
                             ->addDefaultsIfNotSet()
                             ->children()

+ 19 - 6
src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php

@@ -110,13 +110,27 @@ class SecurityExtension extends Extension
         $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
         $loader->load('security_acl.xml');
 
-        if (isset($config['connection'])) {
-            $container->setAlias('security.acl.dbal.connection', sprintf('doctrine.dbal.%s_connection', $config['connection']));
-        }
-
         if (isset($config['cache']['id'])) {
             $container->setAlias('security.acl.cache', $config['cache']['id']);
         }
+        $container->getDefinition('security.acl.voter.basic_permissions')->addArgument($config['voter']['allow_if_object_identity_unavailable']);
+
+        // custom ACL provider
+        if (isset($config['provider'])) {
+            $container->setAlias('security.acl.provider', $config['provider']);
+            return;
+        }
+
+        $this->configureDbalAclProvider($config, $container, $loader);
+    }
+
+    private function configureDbalAclProvider(array $config, ContainerBuilder $container, $loader)
+    {
+        $loader->load('security_acl_dbal.xml');
+
+        if (isset($config['connection'])) {
+            $container->setAlias('security.acl.dbal.connection', sprintf('doctrine.dbal.%s_connection', $config['connection']));
+        }
         $container->getDefinition('security.acl.cache.doctrine')->addArgument($config['cache']['prefix']);
 
         $container->setParameter('security.acl.dbal.class_table_name', $config['tables']['class']);
@@ -124,8 +138,6 @@ class SecurityExtension extends Extension
         $container->setParameter('security.acl.dbal.oid_table_name', $config['tables']['object_identity']);
         $container->setParameter('security.acl.dbal.oid_ancestors_table_name', $config['tables']['object_identity_ancestors']);
         $container->setParameter('security.acl.dbal.sid_table_name', $config['tables']['security_identity']);
-
-        $container->getDefinition('security.acl.voter.basic_permissions')->addArgument($config['voter']['allow_if_object_identity_unavailable']);
     }
 
     /**
@@ -593,3 +605,4 @@ class SecurityExtension extends Extension
         return 'http://symfony.com/schema/dic/security';
     }
 }
+

+ 0 - 26
src/Symfony/Bundle/SecurityBundle/Resources/config/security_acl.xml

@@ -5,8 +5,6 @@
     xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
 
     <parameters>
-        <parameter key="security.acl.dbal.provider.class">Symfony\Component\Security\Acl\Dbal\MutableAclProvider</parameter>
-
         <parameter key="security.acl.permission_granting_strategy.class">Symfony\Component\Security\Acl\Domain\PermissionGrantingStrategy</parameter>
 
         <parameter key="security.acl.voter.class">Symfony\Component\Security\Acl\Voter\AclVoter</parameter>
@@ -21,8 +19,6 @@
     </parameters>
 
     <services>
-        <service id="security.acl.dbal.connection" alias="database_connection" />
-
         <service id="security.acl.object_identity_retrieval_strategy" class="%security.acl.object_identity_retrieval_strategy.class%" public="false"></service>
 
         <service id="security.acl.security_identity_retrieval_strategy" class="%security.acl.security_identity_retrieval_strategy.class%" public="false">
@@ -30,34 +26,12 @@
             <argument type="service" id="security.authentication.trust_resolver" />
         </service>
 
-        <service id="security.acl.dbal.provider" class="%security.acl.dbal.provider.class%" public="false">
-            <argument type="service" id="security.acl.dbal.connection" />
-            <argument type="service" id="security.acl.permission_granting_strategy" />
-            <argument type="collection">
-                <argument key="class_table_name">%security.acl.dbal.class_table_name%</argument>
-                <argument key="entry_table_name">%security.acl.dbal.entry_table_name%</argument>
-                <argument key="oid_table_name">%security.acl.dbal.oid_table_name%</argument>
-                <argument key="oid_ancestors_table_name">%security.acl.dbal.oid_ancestors_table_name%</argument>
-                <argument key="sid_table_name">%security.acl.dbal.sid_table_name%</argument>
-            </argument>
-            <argument type="service" id="security.acl.cache" on-invalid="null" />
-        </service>
-
-        <service id="security.acl.provider" alias="security.acl.dbal.provider" />
-
         <service id="security.acl.permission_granting_strategy" class="%security.acl.permission_granting_strategy.class%" public="false">
             <call method="setAuditLogger">
                 <argument type="service" id="security.acl.audit_logger" on-invalid="ignore" />
             </call>
         </service>
 
-        <service id="security.acl.cache.doctrine" class="%security.acl.cache.doctrine.class%" public="false">
-            <argument type="service" id="security.acl.cache.doctrine_cache_impl" />
-            <argument type="service" id="security.acl.permission_granting_strategy" />
-        </service>
-
-        <service id="security.acl.cache.doctrine.cache_impl" alias="doctrine.orm.default_result_cache" public="false" />
-
         <service id="security.acl.permission.map" class="%security.acl.permission.map.class%" public="false"></service>
 
         <service id="security.acl.voter.basic_permissions" class="%security.acl.voter.class%" public="false">

+ 38 - 0
src/Symfony/Bundle/SecurityBundle/Resources/config/security_acl_dbal.xml

@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<container xmlns="http://symfony.com/schema/dic/services"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
+
+    <parameters>
+        <parameter key="security.acl.dbal.provider.class">Symfony\Component\Security\Acl\Dbal\MutableAclProvider</parameter>
+    </parameters>
+
+    <services>
+        <service id="security.acl.dbal.connection" alias="database_connection" />
+
+        <service id="security.acl.dbal.provider" class="%security.acl.dbal.provider.class%" public="false">
+            <argument type="service" id="security.acl.dbal.connection" />
+            <argument type="service" id="security.acl.permission_granting_strategy" />
+            <argument type="collection">
+                <argument key="class_table_name">%security.acl.dbal.class_table_name%</argument>
+                <argument key="entry_table_name">%security.acl.dbal.entry_table_name%</argument>
+                <argument key="oid_table_name">%security.acl.dbal.oid_table_name%</argument>
+                <argument key="oid_ancestors_table_name">%security.acl.dbal.oid_ancestors_table_name%</argument>
+                <argument key="sid_table_name">%security.acl.dbal.sid_table_name%</argument>
+            </argument>
+            <argument type="service" id="security.acl.cache" on-invalid="null" />
+        </service>
+
+        <service id="security.acl.provider" alias="security.acl.dbal.provider" />
+
+        <service id="security.acl.cache.doctrine" class="%security.acl.cache.doctrine.class%" public="false">
+            <argument type="service" id="security.acl.cache.doctrine_cache_impl" />
+            <argument type="service" id="security.acl.permission_granting_strategy" />
+        </service>
+
+        <service id="security.acl.cache.doctrine.cache_impl" alias="doctrine.orm.default_result_cache" public="false" />
+
+        <service id="security.acl.permission.map" class="%security.acl.permission.map.class%" public="false"></service>
+    </services>
+</container>

+ 1 - 0
src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1.php

@@ -1,6 +1,7 @@
 <?php
 
 $container->loadFromExtension('security', array(
+    'acl' => array(),
     'encoders' => array(
         'JMS\FooBundle\Entity\User1' => 'plaintext',
         'JMS\FooBundle\Entity\User2' => array(

+ 9 - 0
src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/custom_acl_provider.php

@@ -0,0 +1,9 @@
+<?php
+
+$this->load('container1.php', $container);
+
+$container->loadFromExtension('security', array(
+    'acl' => array(
+        'provider' => 'foo',
+    )
+));

+ 2 - 0
src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1.xml

@@ -6,6 +6,8 @@
     xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
 
     <config>
+        <acl />
+    
         <encoder class="JMS\FooBundle\Entity\User1" algorithm="plaintext" />
 
         <encoder class="JMS\FooBundle\Entity\User2" algorithm="sha1" encode-as-base64="false" iterations="5" />

+ 16 - 0
src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/custom_acl_provider.xml

@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<container xmlns="http://symfony.com/schema/dic/services"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xmlns:sec="http://symfony.com/schema/dic/security"
+    xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
+    
+    <imports>
+        <import resource="container1.xml"/>
+    </imports>
+    
+    <sec:config>
+        <sec:acl provider="foo" />
+    </sec:config>
+
+</container>

+ 1 - 0
src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1.yml

@@ -1,4 +1,5 @@
 security:
+    acl: ~
     encoders:
         JMS\FooBundle\Entity\User1: plaintext
         JMS\FooBundle\Entity\User2:

+ 6 - 0
src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/custom_acl_provider.yml

@@ -0,0 +1,6 @@
+imports:
+    - { resource: container1.yml }
+    
+security:
+    acl:
+        provider: foo

+ 16 - 0
src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/SecurityExtensionTest.php

@@ -150,6 +150,22 @@ abstract class SecurityExtensionTest extends \PHPUnit_Framework_TestCase
         )), $container->getDefinition('security.encoder_factory.generic')->getArguments());
     }
 
+    public function testAcl()
+    {
+        $container = $this->getContainer('container1');
+
+        $this->assertTrue($container->hasDefinition('security.acl.dbal.provider'));
+        $this->assertEquals('security.acl.dbal.provider', (string) $container->getAlias('security.acl.provider'));
+    }
+
+    public function testCustomAclProvider()
+    {
+        $container = $this->getContainer('custom_acl_provider');
+
+        $this->assertFalse($container->hasDefinition('security.acl.dbal.provider'));
+        $this->assertEquals('foo', (string) $container->getAlias('security.acl.provider'));
+    }
+
     protected function getContainer($file)
     {
         $container = new ContainerBuilder();

+ 17 - 1
src/Symfony/Component/HttpFoundation/Request.php

@@ -308,12 +308,28 @@ class Request
         return $this->session;
     }
 
-    public function hasSession()
+    /**
+     * Whether the request contains a Session which was started in one of the
+     * previous requests.
+     *
+     * @return boolean
+     */
+    public function hasPreviousSession()
     {
         // the check for $this->session avoids malicious users trying to fake a session cookie with proper name
         return $this->cookies->has(session_name()) && null !== $this->session;
     }
 
+    /**
+     * Whether the request contains a Session object.
+     *
+     * @return boolean
+     */
+    public function hasSession()
+    {
+        return null !== $this->session;
+    }
+
     public function setSession(Session $session)
     {
         $this->session = $session;

+ 1 - 1
src/Symfony/Component/Security/Http/Firewall/ContextListener.php

@@ -62,7 +62,7 @@ class ContextListener implements ListenerInterface
     {
         $request = $event->getRequest();
 
-        $session = $request->hasSession() ? $request->getSession() : null;
+        $session = $request->hasPreviousSession() ? $request->getSession() : null;
 
         if (null === $session || null === $token = $session->get('_security_'.$this->contextKey)) {
             $this->context->setToken(null);

+ 26 - 0
tests/Symfony/Tests/Component/HttpFoundation/RequestTest.php

@@ -11,6 +11,12 @@
 
 namespace Symfony\Tests\Component\HttpFoundation;
 
+use Symfony\Component\HttpFoundation\HeaderBag;
+
+use Symfony\Component\HttpFoundation\SessionStorage\ArraySessionStorage;
+
+use Symfony\Component\HttpFoundation\Session;
+
 use Symfony\Component\HttpFoundation\Request;
 
 class RequestTest extends \PHPUnit_Framework_TestCase
@@ -721,4 +727,24 @@ class RequestTest extends \PHPUnit_Framework_TestCase
         $this->assertTrue($request->isSecure());
         $this->assertEquals(443, $request->getPort());
     }
+
+    public function testHasSession()
+    {
+        $request = new Request;
+
+        $this->assertFalse($request->hasSession());
+        $request->setSession(new Session(new ArraySessionStorage()));
+        $this->assertTrue($request->hasSession());
+    }
+
+    public function testHasPreviousSession()
+    {
+        $request = new Request;
+
+        $this->assertFalse($request->hasPreviousSession());
+        $request->cookies->set(session_name(), 'foo');
+        $this->assertFalse($request->hasPreviousSession());
+        $request->setSession(new Session(new ArraySessionStorage()));
+        $this->assertTrue($request->hasPreviousSession());
+    }
 }