diff options
10 files changed, 219 insertions, 47 deletions
diff --git a/Core/Authentication/Provider/RememberMeAuthenticationProvider.php b/Core/Authentication/Provider/RememberMeAuthenticationProvider.php index 234bddb..82be1d1 100644 --- a/Core/Authentication/Provider/RememberMeAuthenticationProvider.php +++ b/Core/Authentication/Provider/RememberMeAuthenticationProvider.php @@ -50,7 +50,7 @@ class RememberMeAuthenticationProvider implements AuthenticationProviderInterfac } $user = $token->getUser(); - $this->userChecker->checkPostAuth($user); + $this->userChecker->checkPreAuth($user); $authenticatedToken = new RememberMeToken($user, $this->providerKey, $this->key); $authenticatedToken->setAttributes($token->getAttributes()); diff --git a/Core/Tests/Authentication/Provider/RememberMeAuthenticationProviderTest.php b/Core/Tests/Authentication/Provider/RememberMeAuthenticationProviderTest.php index d278ba4..a6fff4b 100644 --- a/Core/Tests/Authentication/Provider/RememberMeAuthenticationProviderTest.php +++ b/Core/Tests/Authentication/Provider/RememberMeAuthenticationProviderTest.php @@ -12,7 +12,7 @@ namespace Symfony\Component\Security\Core\Tests\Authentication\Provider; use Symfony\Component\Security\Core\Authentication\Provider\RememberMeAuthenticationProvider; -use Symfony\Component\Security\Core\Exception\AccountExpiredException; +use Symfony\Component\Security\Core\Exception\DisabledException; use Symfony\Component\Security\Core\Role\Role; class RememberMeAuthenticationProviderTest extends \PHPUnit_Framework_TestCase @@ -45,15 +45,14 @@ class RememberMeAuthenticationProviderTest extends \PHPUnit_Framework_TestCase } /** - * @expectedException \Symfony\Component\Security\Core\Exception\AccountExpiredException + * @expectedException \Symfony\Component\Security\Core\Exception\DisabledException */ - public function testAuthenticateWhenPostChecksFails() + public function testAuthenticateWhenPreChecksFails() { $userChecker = $this->getMock('Symfony\Component\Security\Core\User\UserCheckerInterface'); $userChecker->expects($this->once()) - ->method('checkPostAuth') - ->will($this->throwException(new AccountExpiredException())) - ; + ->method('checkPreAuth') + ->will($this->throwException(new DisabledException())); $provider = $this->getProvider($userChecker); @@ -65,8 +64,7 @@ class RememberMeAuthenticationProviderTest extends \PHPUnit_Framework_TestCase $user = $this->getMock('Symfony\Component\Security\Core\User\UserInterface'); $user->expects($this->exactly(2)) ->method('getRoles') - ->will($this->returnValue(array('ROLE_FOO'))) - ; + ->will($this->returnValue(array('ROLE_FOO'))); $provider = $this->getProvider(); @@ -86,16 +84,14 @@ class RememberMeAuthenticationProviderTest extends \PHPUnit_Framework_TestCase $user ->expects($this->any()) ->method('getRoles') - ->will($this->returnValue(array())) - ; + ->will($this->returnValue(array())); } $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\RememberMeToken', array('getProviderKey'), array($user, 'foo', $key)); $token ->expects($this->once()) ->method('getProviderKey') - ->will($this->returnValue('foo')) - ; + ->will($this->returnValue('foo')); return $token; } diff --git a/Core/Tests/Validator/Constraints/UserPasswordValidatorTest.php b/Core/Tests/Validator/Constraints/UserPasswordValidatorTest.php index 10f692c..ef93e25 100644 --- a/Core/Tests/Validator/Constraints/UserPasswordValidatorTest.php +++ b/Core/Tests/Validator/Constraints/UserPasswordValidatorTest.php @@ -92,7 +92,8 @@ class UserPasswordValidatorTest extends AbstractConstraintValidatorTest $this->validator->validate('secret', $constraint); - $this->assertViolation('myMessage'); + $this->buildViolation('myMessage') + ->assertRaised(); } /** diff --git a/Http/Authentication/CustomAuthenticationFailureHandler.php b/Http/Authentication/CustomAuthenticationFailureHandler.php new file mode 100644 index 0000000..35bfc05 --- /dev/null +++ b/Http/Authentication/CustomAuthenticationFailureHandler.php @@ -0,0 +1,45 @@ +<?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\Authentication; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\Security\Core\Exception\AuthenticationException; + +/** + * @author Fabien Potencier <fabien@symfony.com> + */ +class CustomAuthenticationFailureHandler implements AuthenticationFailureHandlerInterface +{ + private $handler; + + /** + * Constructor. + * + * @param AuthenticationFailureHandlerInterface $handler An AuthenticationFailureHandlerInterface instance + * @param array $options Options for processing a successful authentication attempt + */ + public function __construct(AuthenticationFailureHandlerInterface $handler, array $options) + { + $this->handler = $handler; + if (method_exists($handler, 'setOptions')) { + $this->handler->setOptions($options); + } + } + + /** + * {@inheritdoc} + */ + public function onAuthenticationFailure(Request $request, AuthenticationException $exception) + { + return $this->handler->onAuthenticationFailure($request, $exception); + } +} diff --git a/Http/Authentication/CustomAuthenticationSuccessHandler.php b/Http/Authentication/CustomAuthenticationSuccessHandler.php new file mode 100644 index 0000000..abbb81b --- /dev/null +++ b/Http/Authentication/CustomAuthenticationSuccessHandler.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\Authentication; + +use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; +use Symfony\Component\HttpFoundation\Request; + +/** + * @author Fabien Potencier <fabien@symfony.com> + */ +class CustomAuthenticationSuccessHandler implements AuthenticationSuccessHandlerInterface +{ + private $handler; + + /** + * Constructor. + * + * @param AuthenticationSuccessHandlerInterface $handler An AuthenticationFailureHandlerInterface instance + * @param array $options Options for processing a successful authentication attempt + * @param string $providerKey The provider key + */ + public function __construct(AuthenticationSuccessHandlerInterface $handler, array $options, $providerKey) + { + $this->handler = $handler; + if (method_exists($handler, 'setOptions')) { + $this->handler->setOptions($options); + } + if (method_exists($handler, 'setProviderKey')) { + $this->handler->setProviderKey($providerKey); + } + } + + /** + * {@inheritdoc} + */ + public function onAuthenticationSuccess(Request $request, TokenInterface $token) + { + return $this->handler->onAuthenticationSuccess($request, $token); + } +} diff --git a/Http/Authentication/DefaultAuthenticationFailureHandler.php b/Http/Authentication/DefaultAuthenticationFailureHandler.php index db96e67..658a999 100644 --- a/Http/Authentication/DefaultAuthenticationFailureHandler.php +++ b/Http/Authentication/DefaultAuthenticationFailureHandler.php @@ -34,6 +34,12 @@ class DefaultAuthenticationFailureHandler implements AuthenticationFailureHandle protected $httpUtils; protected $logger; protected $options; + protected $defaultOptions = array( + 'failure_path' => null, + 'failure_forward' => false, + 'login_path' => '/login', + 'failure_path_parameter' => '_failure_path', + ); /** * Constructor. @@ -43,18 +49,32 @@ class DefaultAuthenticationFailureHandler implements AuthenticationFailureHandle * @param array $options Options for processing a failed authentication attempt. * @param LoggerInterface $logger Optional logger */ - public function __construct(HttpKernelInterface $httpKernel, HttpUtils $httpUtils, array $options, LoggerInterface $logger = null) + public function __construct(HttpKernelInterface $httpKernel, HttpUtils $httpUtils, array $options = array(), LoggerInterface $logger = null) { $this->httpKernel = $httpKernel; - $this->httpUtils = $httpUtils; - $this->logger = $logger; + $this->httpUtils = $httpUtils; + $this->logger = $logger; + $this->setOptions($options); + } - $this->options = array_merge(array( - 'failure_path' => null, - 'failure_forward' => false, - 'login_path' => '/login', - 'failure_path_parameter' => '_failure_path', - ), $options); + /** + * Gets the options. + * + * @return array An array of options + */ + public function getOptions() + { + return $this->options; + } + + /** + * Sets the options. + * + * @param array $options An array of options + */ + public function setOptions(array $options) + { + $this->options = array_merge($this->defaultOptions, $options); } /** diff --git a/Http/Authentication/DefaultAuthenticationSuccessHandler.php b/Http/Authentication/DefaultAuthenticationSuccessHandler.php index 54d6fc1..0ee11b4 100644 --- a/Http/Authentication/DefaultAuthenticationSuccessHandler.php +++ b/Http/Authentication/DefaultAuthenticationSuccessHandler.php @@ -27,6 +27,13 @@ class DefaultAuthenticationSuccessHandler implements AuthenticationSuccessHandle protected $httpUtils; protected $options; protected $providerKey; + protected $defaultOptions = array( + 'always_use_default_target_path' => false, + 'default_target_path' => '/', + 'login_path' => '/login', + 'target_path_parameter' => '_target_path', + 'use_referer' => false, + ); /** * Constructor. @@ -34,17 +41,10 @@ class DefaultAuthenticationSuccessHandler implements AuthenticationSuccessHandle * @param HttpUtils $httpUtils * @param array $options Options for processing a successful authentication attempt. */ - public function __construct(HttpUtils $httpUtils, array $options) + public function __construct(HttpUtils $httpUtils, array $options = array()) { - $this->httpUtils = $httpUtils; - - $this->options = array_merge(array( - 'always_use_default_target_path' => false, - 'default_target_path' => '/', - 'login_path' => '/login', - 'target_path_parameter' => '_target_path', - 'use_referer' => false, - ), $options); + $this->httpUtils = $httpUtils; + $this->setOptions($options); } /** @@ -56,6 +56,26 @@ class DefaultAuthenticationSuccessHandler implements AuthenticationSuccessHandle } /** + * Gets the options. + * + * @return array An array of options + */ + public function getOptions() + { + return $this->options; + } + + /** + * Sets the options. + * + * @param array $options An array of options + */ + public function setOptions(array $options) + { + $this->options = array_merge($this->defaultOptions, $options); + } + + /** * Get the provider key. * * @return string diff --git a/Http/Firewall/AnonymousAuthenticationListener.php b/Http/Firewall/AnonymousAuthenticationListener.php index 59f05ff..e3c35a0 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, LoggerInterface $logger = null, AuthenticationManagerInterface $authenticationManager = 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,21 @@ class AnonymousAuthenticationListener implements ListenerInterface return; } - $this->context->setToken(new AnonymousToken($this->key, 'anon.', array())); + try { + $token = new AnonymousToken($this->key, 'anon.', array()); + if (null !== $this->authenticationManager) { + $token = $this->authenticationManager->authenticate($token); + } - if (null !== $this->logger) { - $this->logger->info('Populated SecurityContext with an anonymous Token'); + $this->context->setToken($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/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..0f43aa0 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', null, $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', null, $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', $logger, $authenticationManager); $listener->handle($this->getMock('Symfony\Component\HttpKernel\Event\GetResponseEvent', array(), array(), '', false)); } } |