diff options
Diffstat (limited to 'Http')
6 files changed, 194 insertions, 16 deletions
diff --git a/Http/Firewall/AnonymousAuthenticationListener.php b/Http/Firewall/AnonymousAuthenticationListener.php index 59f05ff..986c9a8 100644 --- a/Http/Firewall/AnonymousAuthenticationListener.php +++ b/Http/Firewall/AnonymousAuthenticationListener.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Security\Http\Firewall; +use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface; +use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Core\SecurityContextInterface; use Psr\Log\LoggerInterface; use Symfony\Component\HttpKernel\Event\GetResponseEvent; @@ -26,13 +28,15 @@ class AnonymousAuthenticationListener implements ListenerInterface { private $context; private $key; + private $authenticationManager; private $logger; - public function __construct(SecurityContextInterface $context, $key, LoggerInterface $logger = null) + public function __construct(SecurityContextInterface $context, $key, AuthenticationManagerInterface $authenticationManager, LoggerInterface $logger = null) { - $this->context = $context; - $this->key = $key; - $this->logger = $logger; + $this->context = $context; + $this->key = $key; + $this->authenticationManager = $authenticationManager; + $this->logger = $logger; } /** @@ -46,10 +50,17 @@ class AnonymousAuthenticationListener implements ListenerInterface return; } - $this->context->setToken(new AnonymousToken($this->key, 'anon.', array())); + try { + $token = $this->authenticationManager->authenticate(new AnonymousToken($this->key, 'anon.', array())); + $this->context->setToken($token); - if (null !== $this->logger) { - $this->logger->info('Populated SecurityContext with an anonymous Token'); + if (null !== $this->logger) { + $this->logger->info('Populated SecurityContext with an anonymous Token'); + } + } catch (AuthenticationException $failed) { + if (null !== $this->logger) { + $this->logger->info(sprintf('Anonymous authentication failed: %s', $failed->getMessage())); + } } } } diff --git a/Http/Firewall/RemoteUserAuthenticationListener.php b/Http/Firewall/RemoteUserAuthenticationListener.php new file mode 100644 index 0000000..f190a17 --- /dev/null +++ b/Http/Firewall/RemoteUserAuthenticationListener.php @@ -0,0 +1,49 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Security\Http\Firewall; + +use Symfony\Component\Security\Core\SecurityContextInterface; +use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface; +use Psr\Log\LoggerInterface; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\Security\Core\Exception\BadCredentialsException; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; + +/** + * REMOTE_USER authentication listener. + * + * @author Fabien Potencier <fabien@symfony.com> + * @author Maxime Douailin <maxime.douailin@gmail.com> + */ +class RemoteUserAuthenticationListener extends AbstractPreAuthenticatedListener +{ + private $userKey; + + public function __construct(SecurityContextInterface $securityContext, AuthenticationManagerInterface $authenticationManager, $providerKey, $userKey = 'REMOTE_USER', LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null) + { + parent::__construct($securityContext, $authenticationManager, $providerKey, $logger, $dispatcher); + + $this->userKey = $userKey; + } + + /** + * {@inheritdoc} + */ + protected function getPreAuthenticatedData(Request $request) + { + if (!$request->server->has($this->userKey)) { + throw new BadCredentialsException(sprintf('User key was not found: %s', $this->userKey)); + } + + return array($request->server->get($this->userKey), null); + } +} diff --git a/Http/Firewall/SimplePreAuthenticationListener.php b/Http/Firewall/SimplePreAuthenticationListener.php index 258ca96..a6f4f77 100644 --- a/Http/Firewall/SimplePreAuthenticationListener.php +++ b/Http/Firewall/SimplePreAuthenticationListener.php @@ -76,6 +76,12 @@ class SimplePreAuthenticationListener implements ListenerInterface try { $token = $this->simpleAuthenticator->createToken($request, $this->providerKey); + + // allow null to be returned to skip authentication + if (null === $token) { + return; + } + $token = $this->authenticationManager->authenticate($token); $this->securityContext->setToken($token); } catch (AuthenticationException $e) { diff --git a/Http/Tests/Firewall/AnonymousAuthenticationListenerTest.php b/Http/Tests/Firewall/AnonymousAuthenticationListenerTest.php index 1fb7350..e6bab4e 100644 --- a/Http/Tests/Firewall/AnonymousAuthenticationListenerTest.php +++ b/Http/Tests/Firewall/AnonymousAuthenticationListenerTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Security\Http\Tests\Firewall; +use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken; use Symfony\Component\Security\Http\Firewall\AnonymousAuthenticationListener; class AnonymousAuthenticationListenerTest extends \PHPUnit_Framework_TestCase @@ -28,7 +29,13 @@ class AnonymousAuthenticationListenerTest extends \PHPUnit_Framework_TestCase ->method('setToken') ; - $listener = new AnonymousAuthenticationListener($context, 'TheKey'); + $authenticationManager = $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface'); + $authenticationManager + ->expects($this->never()) + ->method('authenticate') + ; + + $listener = new AnonymousAuthenticationListener($context, 'TheKey', $authenticationManager); $listener->handle($this->getMock('Symfony\Component\HttpKernel\Event\GetResponseEvent', array(), array(), '', false)); } @@ -40,16 +47,27 @@ class AnonymousAuthenticationListenerTest extends \PHPUnit_Framework_TestCase ->method('getToken') ->will($this->returnValue(null)) ; - $context + + $anonymousToken = new AnonymousToken('TheKey', 'anon.', array()); + + $authenticationManager = $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface'); + $authenticationManager ->expects($this->once()) - ->method('setToken') + ->method('authenticate') ->with(self::logicalAnd( - $this->isInstanceOf('Symfony\Component\Security\Core\Authentication\Token\AnonymousToken'), - $this->attributeEqualTo('key', 'TheKey') + $this->isInstanceOf('Symfony\Component\Security\Core\Authentication\Token\AnonymousToken'), + $this->attributeEqualTo('key', 'TheKey') )) + ->will($this->returnValue($anonymousToken)) ; - $listener = new AnonymousAuthenticationListener($context, 'TheKey'); + $context + ->expects($this->once()) + ->method('setToken') + ->with($anonymousToken) + ; + + $listener = new AnonymousAuthenticationListener($context, 'TheKey', $authenticationManager); $listener->handle($this->getMock('Symfony\Component\HttpKernel\Event\GetResponseEvent', array(), array(), '', false)); } @@ -66,7 +84,9 @@ class AnonymousAuthenticationListenerTest extends \PHPUnit_Framework_TestCase ->with('Populated SecurityContext with an anonymous Token') ; - $listener = new AnonymousAuthenticationListener($context, 'TheKey', $logger); + $authenticationManager = $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface'); + + $listener = new AnonymousAuthenticationListener($context, 'TheKey', $authenticationManager, $logger); $listener->handle($this->getMock('Symfony\Component\HttpKernel\Event\GetResponseEvent', array(), array(), '', false)); } } diff --git a/Http/Tests/Firewall/ContextListenerTest.php b/Http/Tests/Firewall/ContextListenerTest.php index d6bc5b4..90af07e 100644 --- a/Http/Tests/Firewall/ContextListenerTest.php +++ b/Http/Tests/Firewall/ContextListenerTest.php @@ -18,6 +18,7 @@ use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; use Symfony\Component\HttpKernel\Event\FilterResponseEvent; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\KernelEvents; +use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage; use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; use Symfony\Component\Security\Core\SecurityContext; use Symfony\Component\Security\Http\Firewall\ContextListener; @@ -27,8 +28,8 @@ class ContextListenerTest extends \PHPUnit_Framework_TestCase protected function setUp() { $this->securityContext = new SecurityContext( - $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface'), - $this->getMock('Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface') + new TokenStorage(), + $this->getMock('Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface') ); } diff --git a/Http/Tests/Firewall/RemoteUserAuthenticationListenerTest.php b/Http/Tests/Firewall/RemoteUserAuthenticationListenerTest.php new file mode 100644 index 0000000..2bc1ad6 --- /dev/null +++ b/Http/Tests/Firewall/RemoteUserAuthenticationListenerTest.php @@ -0,0 +1,91 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Security\Http\Tests\Firewall; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\Security\Http\Firewall\RemoteUserAuthenticationListener; + +class RemoteUserAuthenticationListenerTest extends \PHPUnit_Framework_TestCase +{ + public function testGetPreAuthenticatedData() + { + $serverVars = array( + 'REMOTE_USER' => 'TheUser' + ); + + $request = new Request(array(), array(), array(), array(), array(), $serverVars); + + $context = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface'); + + $authenticationManager = $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface'); + + $listener = new RemoteUserAuthenticationListener( + $context, + $authenticationManager, + 'TheProviderKey' + ); + + $method = new \ReflectionMethod($listener, 'getPreAuthenticatedData'); + $method->setAccessible(true); + + $result = $method->invokeArgs($listener, array($request)); + $this->assertSame($result, array('TheUser', null)); + } + + /** + * @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException + */ + public function testGetPreAuthenticatedDataNoUser() + { + $request = new Request(array(), array(), array(), array(), array(), array()); + + $context = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface'); + + $authenticationManager = $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface'); + + $listener = new RemoteUserAuthenticationListener( + $context, + $authenticationManager, + 'TheProviderKey' + ); + + $method = new \ReflectionMethod($listener, 'getPreAuthenticatedData'); + $method->setAccessible(true); + + $result = $method->invokeArgs($listener, array($request)); + } + + public function testGetPreAuthenticatedDataWithDifferentKeys() + { + $userCredentials = array('TheUser', null); + + $request = new Request(array(), array(), array(), array(), array(), array( + 'TheUserKey' => 'TheUser' + )); + $context = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface'); + + $authenticationManager = $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface'); + + $listener = new RemoteUserAuthenticationListener( + $context, + $authenticationManager, + 'TheProviderKey', + 'TheUserKey' + ); + + $method = new \ReflectionMethod($listener, 'getPreAuthenticatedData'); + $method->setAccessible(true); + + $result = $method->invokeArgs($listener, array($request)); + $this->assertSame($result, $userCredentials); + } +} |