diff --git a/UPGRADE-3.3.md b/UPGRADE-3.3.md index 490415f1a5979..f15fa7dbd592b 100644 --- a/UPGRADE-3.3.md +++ b/UPGRADE-3.3.md @@ -94,6 +94,9 @@ Process Security -------- + * Deprecated the ability to pass multiple user providers to the `ContextListener`. Pass only the user provider responsible + for the active firewall instead. + * The `RoleInterface` has been deprecated. Extend the `Symfony\Component\Security\Core\Role\Role` class in your custom role implementations instead. diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index ad00aebc787a8..8b443a5bc855e 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -252,6 +252,9 @@ Process Security -------- + * Dropped support for passing multiple user providers to the `ContextListener`. Pass only the user provider responsible + for the active firewall instead. + * The `RoleInterface` has been removed. Extend the `Symfony\Component\Security\Core\Role\Role` class instead. diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php index a04e29973a465..9cff0b3c1a6b8 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php @@ -234,16 +234,6 @@ private function createFirewalls($config, ContainerBuilder $container) $firewalls = $config['firewalls']; $providerIds = $this->createUserProviders($config, $container); - // make the ContextListener aware of the configured user providers - $definition = $container->getDefinition('security.context_listener'); - $arguments = $definition->getArguments(); - $userProviders = array(); - foreach ($providerIds as $userProviderId) { - $userProviders[] = new Reference($userProviderId); - } - $arguments[1] = $userProviders; - $definition->setArguments($arguments); - // load firewall map $mapDef = $container->getDefinition('security.firewall.map'); $map = $authenticationProviders = $contextRefs = array(); @@ -327,7 +317,7 @@ private function createFirewall(ContainerBuilder $container, $id, $firewall, &$a $contextKey = $firewall['context']; } - $listeners[] = new Reference($this->createContextListener($container, $contextKey)); + $listeners[] = new Reference($this->createContextListener($container, $contextKey, $defaultProvider)); } $config->replaceArgument(6, $contextKey); @@ -436,7 +426,7 @@ private function createFirewall(ContainerBuilder $container, $id, $firewall, &$a return array($matcher, $listeners, $exceptionListener); } - private function createContextListener($container, $contextKey) + private function createContextListener($container, $contextKey, $providerId) { if (isset($this->contextListeners[$contextKey])) { return $this->contextListeners[$contextKey]; @@ -444,6 +434,7 @@ private function createContextListener($container, $contextKey) $listenerId = 'security.context_listener.'.count($this->contextListeners); $listener = $container->setDefinition($listenerId, new ChildDefinition('security.context_listener')); + $listener->replaceArgument(1, new Reference($providerId)); $listener->replaceArgument(2, $contextKey); return $this->contextListeners[$contextKey] = $listenerId; diff --git a/src/Symfony/Component/Security/CHANGELOG.md b/src/Symfony/Component/Security/CHANGELOG.md index 6bebfba400ca2..9ac9c54981461 100644 --- a/src/Symfony/Component/Security/CHANGELOG.md +++ b/src/Symfony/Component/Security/CHANGELOG.md @@ -1,6 +1,12 @@ CHANGELOG ========= +3.3.0 +----- + + * Deprecated the ability to pass multiple user providers to the `ContextListener`. Pass only the user provider responsible + for the active firewall instead. + 3.2.0 ----- diff --git a/src/Symfony/Component/Security/Http/Firewall/ContextListener.php b/src/Symfony/Component/Security/Http/Firewall/ContextListener.php index 4d6f3f81f1b49..ef57ac42c4401 100644 --- a/src/Symfony/Component/Security/Http/Firewall/ContextListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/ContextListener.php @@ -44,12 +44,26 @@ class ContextListener implements ListenerInterface private $registered; private $trustResolver; - public function __construct(TokenStorageInterface $tokenStorage, array $userProviders, $contextKey, LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null, AuthenticationTrustResolverInterface $trustResolver = null) + /** + * @param TokenStorageInterface $tokenStorage + * @param UserProviderInterface|UserProviderInterface[] $userProviders + * @param string $contextKey + * @param LoggerInterface|null $logger + * @param EventDispatcherInterface|null $dispatcher + * @param AuthenticationTrustResolverInterface|null $trustResolver + */ + public function __construct(TokenStorageInterface $tokenStorage, $userProviders, $contextKey, LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null, AuthenticationTrustResolverInterface $trustResolver = null) { if (empty($contextKey)) { throw new \InvalidArgumentException('$contextKey must not be empty.'); } + if (is_array($userProviders)) { + @trigger_error(sprintf('Being able to pass multiple user providers to the constructor of %s is deprecated since version 3.3 and will not be supported anymore in 4.0. Only pass the user provider for the current firewall context instead.', __CLASS__), E_USER_DEPRECATED); + } else { + $userProviders = array($userProviders); + } + foreach ($userProviders as $userProvider) { if (!$userProvider instanceof UserProviderInterface) { throw new \InvalidArgumentException(sprintf('User provider "%s" must implement "Symfony\Component\Security\Core\User\UserProviderInterface".', get_class($userProvider))); diff --git a/src/Symfony/Component/Security/Http/Tests/Firewall/ContextListenerTest.php b/src/Symfony/Component/Security/Http/Tests/Firewall/ContextListenerTest.php index be7b72f5d0f4e..1ed0663aaeeda 100644 --- a/src/Symfony/Component/Security/Http/Tests/Firewall/ContextListenerTest.php +++ b/src/Symfony/Component/Security/Http/Tests/Firewall/ContextListenerTest.php @@ -22,6 +22,7 @@ use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage; use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; +use Symfony\Component\Security\Core\User\UserProviderInterface; use Symfony\Component\Security\Http\Firewall\ContextListener; use Symfony\Component\EventDispatcher\EventDispatcher; @@ -35,12 +36,13 @@ public function testItRequiresContextKey() { new ContextListener( $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface')->getMock(), - array(), + $this->getMockBuilder(UserProviderInterface::class)->getMock(), '' ); } /** + * @group legacy * @expectedException \InvalidArgumentException * @expectedExceptionMessage User provider "stdClass" must implement "Symfony\Component\Security\Core\User\UserProviderInterface */ @@ -109,7 +111,7 @@ public function testOnKernelResponseWithoutSession() new Response() ); - $listener = new ContextListener($tokenStorage, array(), 'session', null, new EventDispatcher()); + $listener = new ContextListener($tokenStorage, $this->getMockBuilder(UserProviderInterface::class)->getMock(), 'session', null, new EventDispatcher()); $listener->onKernelResponse($event); $this->assertTrue($session->isStarted()); @@ -128,7 +130,7 @@ public function testOnKernelResponseWithoutSessionNorToken() new Response() ); - $listener = new ContextListener(new TokenStorage(), array(), 'session', null, new EventDispatcher()); + $listener = new ContextListener(new TokenStorage(), $this->getMockBuilder(UserProviderInterface::class)->getMock(), 'session', null, new EventDispatcher()); $listener->onKernelResponse($event); $this->assertFalse($session->isStarted()); @@ -163,7 +165,7 @@ public function testInvalidTokenInSession($token) ->method('setToken') ->with(null); - $listener = new ContextListener($tokenStorage, array(), 'key123'); + $listener = new ContextListener($tokenStorage, $this->getMockBuilder(UserProviderInterface::class)->getMock(), 'key123'); $listener->handle($event); } @@ -184,7 +186,7 @@ public function testHandleAddsKernelResponseListener() ->disableOriginalConstructor() ->getMock(); - $listener = new ContextListener($tokenStorage, array(), 'key123', null, $dispatcher); + $listener = new ContextListener($tokenStorage, $this->getMockBuilder(UserProviderInterface::class)->getMock(), 'key123', null, $dispatcher); $event->expects($this->any()) ->method('isMasterRequest') @@ -208,7 +210,7 @@ public function testOnKernelResponseListenerRemovesItself() ->disableOriginalConstructor() ->getMock(); - $listener = new ContextListener($tokenStorage, array(), 'key123', null, $dispatcher); + $listener = new ContextListener($tokenStorage, $this->getMockBuilder(UserProviderInterface::class)->getMock(), 'key123', null, $dispatcher); $request = $this->getMockBuilder('Symfony\Component\HttpFoundation\Request')->getMock(); $request->expects($this->any()) @@ -242,7 +244,7 @@ public function testHandleRemovesTokenIfNoPreviousSessionWasFound() $tokenStorage = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface')->getMock(); $tokenStorage->expects($this->once())->method('setToken')->with(null); - $listener = new ContextListener($tokenStorage, array(), 'key123'); + $listener = new ContextListener($tokenStorage, $this->getMockBuilder(UserProviderInterface::class)->getMock(), 'key123'); $listener->handle($event); } @@ -268,7 +270,7 @@ protected function runSessionOnKernelResponse($newToken, $original = null) new Response() ); - $listener = new ContextListener($tokenStorage, array(), 'session', null, new EventDispatcher()); + $listener = new ContextListener($tokenStorage, $this->getMockBuilder(UserProviderInterface::class)->getMock(), 'session', null, new EventDispatcher()); $listener->onKernelResponse($event); return $session;