diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/RememberMeFactory.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/RememberMeFactory.php
index 288ea1e824..679b1db96f 100644
--- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/RememberMeFactory.php
+++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/RememberMeFactory.php
@@ -102,6 +102,7 @@ class RememberMeFactory implements SecurityFactoryInterface
$listenerId = 'security.authentication.listener.rememberme.'.$id;
$listener = $container->setDefinition($listenerId, new DefinitionDecorator('security.authentication.listener.rememberme'));
$listener->replaceArgument(1, new Reference($rememberMeServicesId));
+ $listener->replaceArgument(4, $config['catch_exceptions']);
return array($authProviderId, $listenerId, $defaultEntryPoint);
}
@@ -130,6 +131,7 @@ class RememberMeFactory implements SecurityFactoryInterface
->end()
->prototype('scalar')->end()
->end()
+ ->scalarNode('catch_exceptions')->defaultTrue()->end()
;
foreach ($this->options as $name => $value) {
diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/config/security_rememberme.xml b/src/Symfony/Bundle/SecurityBundle/Resources/config/security_rememberme.xml
index eec67aa868..15131e96c7 100644
--- a/src/Symfony/Bundle/SecurityBundle/Resources/config/security_rememberme.xml
+++ b/src/Symfony/Bundle/SecurityBundle/Resources/config/security_rememberme.xml
@@ -24,13 +24,14 @@
+
-
+
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php
index 3165b2f34b..cf79e9bfd9 100644
--- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php
@@ -82,6 +82,7 @@ abstract class CompleteConfigurationTest extends \PHPUnit_Framework_TestCase
'security.authentication.listener.form.secure',
'security.authentication.listener.basic.secure',
'security.authentication.listener.digest.secure',
+ 'security.authentication.listener.rememberme.secure',
'security.authentication.listener.anonymous.secure',
'security.access_listener',
'security.authentication.switchuser_listener.secure',
@@ -219,6 +220,20 @@ abstract class CompleteConfigurationTest extends \PHPUnit_Framework_TestCase
$this->assertEquals('foo', (string) $container->getAlias('security.acl.provider'));
}
+ public function testRememberMeThrowExceptionsDefault()
+ {
+ $container = $this->getContainer('container1');
+ $this->assertTrue($container->getDefinition('security.authentication.listener.rememberme.secure')->getArgument(4));
+ }
+
+ public function testRememberMeThrowExceptions()
+ {
+ $container = $this->getContainer('remember_me_options');
+ $service = $container->getDefinition('security.authentication.listener.rememberme.main');
+ $this->assertEquals('security.authentication.rememberme.services.persistent.main', $service->getArgument(1));
+ $this->assertFalse($service->getArgument(4));
+ }
+
protected function getContainer($file)
{
$container = new ContainerBuilder();
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1.php
index 9a15ea5fd7..1a24528b77 100644
--- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1.php
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1.php
@@ -70,6 +70,7 @@ $container->loadFromExtension('security', array(
'switch_user' => true,
'x509' => true,
'logout' => true,
+ 'remember_me' => array('key' => 'TheKey')
),
'host' => array(
'pattern' => '/test',
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/remember_me_options.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/remember_me_options.php
new file mode 100644
index 0000000000..ef4a7887d1
--- /dev/null
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/remember_me_options.php
@@ -0,0 +1,17 @@
+loadFromExtension('security', array(
+ 'providers' => array(
+ 'default' => array('id' => 'foo'),
+ ),
+
+ 'firewalls' => array(
+ 'main' => array(
+ 'form_login' => true,
+ 'remember_me' => array(
+ 'key' => 'TheyKey',
+ 'catch_exceptions' => false,
+ 'token_provider' => 'token_provider_id',
+ )
+ )
+ ),
+));
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1.xml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1.xml
index 2368aa312d..e520c1120f 100644
--- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1.xml
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1.xml
@@ -55,6 +55,7 @@
+
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/remember_me_options.xml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/remember_me_options.xml
new file mode 100644
index 0000000000..1674756891
--- /dev/null
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/remember_me_options.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1.yml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1.yml
index 9bfe29230b..a17b3c810d 100644
--- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1.yml
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1.yml
@@ -53,6 +53,8 @@ security:
switch_user: true
x509: true
logout: true
+ remember_me:
+ key: TheKey
host:
pattern: /test
host: foo\.example\.org
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/remember_me_options.yml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/remember_me_options.yml
new file mode 100644
index 0000000000..3a38b33c52
--- /dev/null
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/remember_me_options.yml
@@ -0,0 +1,12 @@
+security:
+ providers:
+ default:
+ id: foo
+
+ firewalls:
+ main:
+ form_login: true
+ remember_me:
+ key: TheKey
+ catch_exceptions: false
+ token_provider: token_provider_id
diff --git a/src/Symfony/Component/Security/Http/Firewall/RememberMeListener.php b/src/Symfony/Component/Security/Http/Firewall/RememberMeListener.php
index 6ca384296c..44000d364d 100644
--- a/src/Symfony/Component/Security/Http/Firewall/RememberMeListener.php
+++ b/src/Symfony/Component/Security/Http/Firewall/RememberMeListener.php
@@ -33,6 +33,7 @@ class RememberMeListener implements ListenerInterface
private $authenticationManager;
private $logger;
private $dispatcher;
+ private $catchExceptions = true;
/**
* Constructor.
@@ -42,14 +43,16 @@ class RememberMeListener implements ListenerInterface
* @param AuthenticationManagerInterface $authenticationManager
* @param LoggerInterface $logger
* @param EventDispatcherInterface $dispatcher
+ * @param bool $catchExceptions
*/
- public function __construct(SecurityContextInterface $securityContext, RememberMeServicesInterface $rememberMeServices, AuthenticationManagerInterface $authenticationManager, LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null)
+ public function __construct(SecurityContextInterface $securityContext, RememberMeServicesInterface $rememberMeServices, AuthenticationManagerInterface $authenticationManager, LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null, $catchExceptions = true)
{
$this->securityContext = $securityContext;
$this->rememberMeServices = $rememberMeServices;
$this->authenticationManager = $authenticationManager;
$this->logger = $logger;
$this->dispatcher = $dispatcher;
+ $this->catchExceptions = $catchExceptions;
}
/**
@@ -90,6 +93,10 @@ class RememberMeListener implements ListenerInterface
}
$this->rememberMeServices->loginFail($request);
+
+ if (!$this->catchExceptions) {
+ throw $failed;
+ }
}
}
}
diff --git a/src/Symfony/Component/Security/Http/Tests/Firewall/RememberMeListenerTest.php b/src/Symfony/Component/Security/Http/Tests/Firewall/RememberMeListenerTest.php
index 950669282c..68dfc1462f 100644
--- a/src/Symfony/Component/Security/Http/Tests/Firewall/RememberMeListenerTest.php
+++ b/src/Symfony/Component/Security/Http/Tests/Firewall/RememberMeListenerTest.php
@@ -14,12 +14,13 @@ namespace Symfony\Component\Security\Http\Tests\Firewall;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Http\Firewall\RememberMeListener;
use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\Security\Http\SecurityEvents;
class RememberMeListenerTest extends \PHPUnit_Framework_TestCase
{
public function testOnCoreSecurityDoesNotTryToPopulateNonEmptySecurityContext()
{
- list($listener, $context, $service,,) = $this->getListener();
+ list($listener, $context,,,,) = $this->getListener();
$context
->expects($this->once())
@@ -99,6 +100,48 @@ class RememberMeListenerTest extends \PHPUnit_Framework_TestCase
$listener->handle($event);
}
+ /**
+ * @expectedException Symfony\Component\Security\Core\Exception\AuthenticationException
+ * @expectedExceptionMessage Authentication failed.
+ */
+ public function testOnCoreSecurityIgnoresAuthenticationOptionallyRethrowsExceptionThrownAuthenticationManagerImplementation()
+ {
+ list($listener, $context, $service, $manager,) = $this->getListener(false, false);
+
+ $context
+ ->expects($this->once())
+ ->method('getToken')
+ ->will($this->returnValue(null))
+ ;
+
+ $service
+ ->expects($this->once())
+ ->method('autoLogin')
+ ->will($this->returnValue($this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')))
+ ;
+
+ $service
+ ->expects($this->once())
+ ->method('loginFail')
+ ;
+
+ $exception = new AuthenticationException('Authentication failed.');
+ $manager
+ ->expects($this->once())
+ ->method('authenticate')
+ ->will($this->throwException($exception))
+ ;
+
+ $event = $this->getGetResponseEvent();
+ $event
+ ->expects($this->once())
+ ->method('getRequest')
+ ->will($this->returnValue(new Request()))
+ ;
+
+ $listener->handle($event);
+ }
+
public function testOnCoreSecurity()
{
list($listener, $context, $service, $manager,) = $this->getListener();
@@ -138,6 +181,55 @@ class RememberMeListenerTest extends \PHPUnit_Framework_TestCase
$listener->handle($event);
}
+ public function testOnCoreSecurityInteractiveLoginEventIsDispatchedIfDispatcherIsPresent()
+ {
+ list($listener, $context, $service, $manager,, $dispatcher) = $this->getListener(true);
+
+ $context
+ ->expects($this->once())
+ ->method('getToken')
+ ->will($this->returnValue(null))
+ ;
+
+ $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
+ $service
+ ->expects($this->once())
+ ->method('autoLogin')
+ ->will($this->returnValue($token))
+ ;
+
+ $context
+ ->expects($this->once())
+ ->method('setToken')
+ ->with($this->equalTo($token))
+ ;
+
+ $manager
+ ->expects($this->once())
+ ->method('authenticate')
+ ->will($this->returnValue($token))
+ ;
+
+ $event = $this->getGetResponseEvent();
+ $request = new Request();
+ $event
+ ->expects($this->once())
+ ->method('getRequest')
+ ->will($this->returnValue($request))
+ ;
+
+ $dispatcher
+ ->expects($this->once())
+ ->method('dispatch')
+ ->with(
+ SecurityEvents::INTERACTIVE_LOGIN,
+ $this->isInstanceOf('Symfony\Component\Security\Http\Event\InteractiveLoginEvent')
+ )
+ ;
+
+ $listener->handle($event);
+ }
+
protected function getGetResponseEvent()
{
return $this->getMock('Symfony\Component\HttpKernel\Event\GetResponseEvent', array(), array(), '', false);
@@ -148,16 +240,18 @@ class RememberMeListenerTest extends \PHPUnit_Framework_TestCase
return $this->getMock('Symfony\Component\HttpKernel\Event\FilterResponseEvent', array(), array(), '', false);
}
- protected function getListener()
+ protected function getListener($withDispatcher = false, $catchExceptions = true)
{
$listener = new RememberMeListener(
$context = $this->getContext(),
$service = $this->getService(),
$manager = $this->getManager(),
- $logger = $this->getLogger()
+ $logger = $this->getLogger(),
+ $dispatcher = ($withDispatcher ? $this->getDispatcher() : null),
+ $catchExceptions
);
- return array($listener, $context, $service, $manager, $logger);
+ return array($listener, $context, $service, $manager, $logger, $dispatcher);
}
protected function getLogger()
@@ -177,8 +271,11 @@ class RememberMeListenerTest extends \PHPUnit_Framework_TestCase
protected function getContext()
{
- return $this->getMockBuilder('Symfony\Component\Security\Core\SecurityContext')
- ->disableOriginalConstructor()
- ->getMock();
+ return $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface');
+ }
+
+ protected function getDispatcher()
+ {
+ return $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface');
}
}