8000 [Security] made it possible to override the default success/failure h… · symfony/symfony@13d37e7 · GitHub
[go: up one dir, main page]

Skip to content

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 13d37e7

Browse files
committed
[Security] made it possible to override the default success/failure handler
1 parent 9752a76 commit 13d37e7

File tree

6 files changed

+173
-60
lines changed

6 files changed

+173
-60
lines changed

src/Symfony/Bundle/SecurityBundle/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
CHANGELOG
22
=========
33

4+
2.6.0
5+
-----
6+
7+
* Added the possibility to override the default success/failure handler
8+
to get the provider key and the options injected
9+
410
2.4.0
511
-----
612

src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/AbstractFactory.php

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
namespace Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory;
1313

1414
use Symfony\Component\Config\Definition\Builder\NodeDefinition;
15-
1615
use Symfony\Component\DependencyInjection\DefinitionDecorator;
1716
use Symfony\Component\DependencyInjection\ContainerBuilder;
1817
use Symfony\Component\DependencyInjection\Reference;
@@ -21,15 +20,16 @@
2120
* AbstractFactory is the base class for all classes inheriting from
2221
* AbstractAuthenticationListener
2322
*
23+
* @author Fabien Potencier <fabien@symfony.com>
2424
* @author Lukas Kahwe Smith <smith@pooteeweet.org>
2525
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
2626
*/
2727
abstract class AbstractFactory implements SecurityFactoryInterface
2828
{
2929
protected $options = array(
30-
'check_path' => '/login_check',
31-
'use_forward' => false,
32-
'require_previous_session' => true,
30+
'check_path' => '/login_check',
31+
'use_forward' => false,
32+
'require_previous_session' => true,
3333
);
3434

3535
protected $defaultSuccessHandlerOptions = array(
@@ -171,28 +171,34 @@ protected function createListener($container, $id, $config, $userProvider)
171171
protected function createAuthenticationSuccessHandler($container, $id, $config)
172172
{
173173
if (isset($config['success_handler'])) {
174-
return $config['success_handler'];
174+
$successHandlerId = $config['success_handler'];
175+
$successHandler = $container->findDefinition($successHandlerId);
176+
} else {
177+
$successHandlerId = $this->getSuccessHandlerId($id);
178+
$successHandler = $container->setDefinition($successHandlerId, new DefinitionDecorator('security.authentication.success_handler'));
175179
}
176180

177-
$successHandlerId = $this->getSuccessHandlerId($id);
178-
179-
$successHandler = $container->setDefinition($successHandlerId, new DefinitionDecorator('security.authentication.success_handler'));
180-
$successHandler->replaceArgument(1, array_intersect_key($config, $this->defaultSuccessHandlerOptions));
181-
$successHandler->addMethodCall('setProviderKey', array($id));
181+
if ($successHandler instanceof DefinitionDecorator && 'security.authentication.success_handler' === $successHandler->getParent()) {
182+
$successHandler->addMethodCall('setOptions', array(array_intersect_key($config, $this->defaultSuccessHandlerOptions)));
183+
$successHandler->addMethodCall('setProviderKey', array($id));
184+
}
182185

183186
return $successHandlerId;
184187
}
185188

186189
protected function createAuthenticationFailureHandler($container, $id, $config)
187190
{
188191
if (isset($config['failure_handler'])) {
189-
return $config['failure_handler'];
192+
$id = $config['failure_handler'];
193+
$failureHandler = $container->findDefinition($id);
194+
} else {
195+
$id = $this->getFailureHandlerId($id);
196+
$failureHandler = $container->setDefinition($id, new DefinitionDecorator('security.authentication.failure_handler'));
190197
}
191198

192-
$id = $this->getFailureHandlerId($id);
193-
194-
$failureHandler = $container->setDefinition($id, new DefinitionDecorator('security.authentication.failure_handler'));
195-
$failureHandler->replaceArgument(2, array_intersect_key($config, $this->defaultFailureHandlerOptions));
199+
if ($failureHandler instanceof DefinitionDecorator && 'security.authentication.failure_handler' === $failureHandler->getParent()) {
200+
$failureHandler->addMethodCall('setOptions', array(array_intersect_key($config, $this->defaultFailureHandlerOptions)));
201+
}
196202

197203
return $id;
198204
}

src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Security/Factory/AbstractFactoryTest.php

Lines changed: 84 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,19 @@
1313

1414
use Symfony\Component\DependencyInjection\Reference;
1515
use Symfony\Component\DependencyInjection\ContainerBuilder;
16+
use Symfony\Component\DependencyInjection\DefinitionDecorator;
1617

1718
class AbstractFactoryTest extends \PHPUnit_Framework_TestCase
1819
{
1920
public function testCreate()
2021
{
21-
list($container,
22-
$authProviderId,
23-
$listenerId,
24-
$entryPointId
25-
) = $this->callFactory('foo', array('use_forward' => true, 'failure_path' => '/foo', 'success_handler' => 'qux', 'failure_handler' => 'bar', 'remember_me' => true), 'user_provider', 'entry_point');
22+
list($container, $authProviderId, $listenerId, $entryPointId) = $this->callFactory('foo', array(
23+
'use_forward' => true,
24+
'failure_path' => '/foo',
25+
'success_handler' => 'custom_success_handler',
26+
'failure_h 6DA7 andler' => 'custom_failure_handler',
27+
'remember_me' => true,
28+
), 'user_provider', 'entry_point');
2629

2730
// auth provider
2831
$this->assertEquals('auth_provider', $authProviderId);
@@ -33,41 +36,95 @@ public function testCreate()
3336
$definition = $container->getDefinition('abstract_listener.foo');
3437
$this->assertEquals(array(
3538
'index_4' => 'foo',
36-
'index_5' => new Reference('qux'),
37-
'index_6' => new Reference('bar'),
39+
'index_5' => new Reference('custom_success_handler'),
40+
'index_6' => new Reference('custom_failure_handler'),
3841
'index_7' => array(
39-
'use_forward' => true,
42+
'use_forward' => true,
4043
),
4144
), $definition->getArguments());
4245

4346
// entry point
4447
$this->assertEquals('entry_point', $entryPointId, '->create() does not change the default entry point.');
4548
}
4649

47-
public function testDefaultFailureHandler()
50+
/**
51+
* @dataProvider getFailureHandlers
52+
*/
53+
public function testDefaultFailureHandler($handlerId, $serviceId, $defaultHandlerInjection)
4854
{
49-
list($container,
50-
$authProviderId,
51-
$listenerId,
52-
$entryPointId
53-
) = $this->callFactory('foo', array('remember_me' => true), 'user_provider', 'entry_point');
55+
$options = array(
56+
'remember_me' => true,
57+
'login_path' => '/bar',
58+
);
59+
60+
if ($serviceId) {
61+
$options['failure_handler'] = $serviceId;
62+
}
63+
64+
list($container, $authProviderId, $listenerId, $entryPointId) = $this->callFactory('foo', $options, 'user_provider', 'entry_point');
5465

5566
$definition = $container->getDefinition('abstract_listener.foo');
5667
$arguments = $definition->getArguments();
57-
$this->assertEquals(new Reference('security.authentication.failure_handler.foo.abstract_factory'), $arguments['index_6']);
68+
$this->assertEquals(new Reference($handlerId), $arguments['index_6']);
69+
$failureHandler = $container->findDefinition((string) $arguments['index_6']);
70+
71+
$methodCalls = $failureHandler->getMethodCalls();
72+
if ($defaultHandlerInjection) {
73+
$this->assertEquals('setOptions', $methodCalls[0][0]);
74+
$this->assertEquals(array('login_path' => '/bar'), $methodCalls[0][1][0]);
75+
} else {
76+
$this->assertCount(0, $methodCalls);
77+
}
78+
}
79+
80+
public function getFailureHandlers()
81+
{
82+
return array(
83+
array('security.authentication.failure_handler.foo.abstract_factory', null, true),
84+
array('custom_failure_handler_default', 'custom_failure_handler_default', true),
85+
array('custom_failure_handler', 'custom_failure_handler', false),
86+
);
5887
}
5988

60-
public function testDefaultSuccessHandler()
89+
/**
90+
* @dataProvider getSuccessHandlers
91+
*/
92+
public function testDefaultSuccessHandler($handlerId, $serviceId, $defaultHandlerInjection)
6193
{
62-
list($container,
63-
$authProviderId,
64-
$listenerId,
65-
$entryPointId
66-
) = $this->callFactory('foo', array('remember_me' => true), 'user_provider', 'entry_point');
94+
$options = array(
95+
'remember_me' => true,
96+
'default_target_path' => '/bar',
97+
);
98+
99+
if ($serviceId) {
100+
$options['success_handler'] = $serviceId;
101+
}
102+
103+
list($container, $authProviderId, $listenerId, $entryPointId) = $this->callFactory('foo', $options, 'user_provider', 'entry_point');
67104

68105
$definition = $container->getDefinition('abstract_listener.foo');
69106
$arguments = $definition->getArguments();
70-
$this->assertEquals(new Reference('security.authentication.success_handler.foo.abstract_factory'), $arguments['index_5']);
107+
$this->assertEquals(new Reference($handlerId), $arguments['index_5']);
108+
$successHandler = $container->findDefinition((string) $arguments['index_5']);
109+
$methodCalls = $successHandler->getMethodCalls();
110+
111+
if ($defaultHandlerInjection) {
112+
$this->assertEquals('setOptions', $methodCalls[0][0]);
113+
$this->assertEquals(array('default_target_path' => '/bar'), $methodCalls[0][1][0]);
114+
$this->assertEquals('setProviderKey', $methodCalls[1][0]);
115+
$this->assertEquals(array('foo'), $methodCalls[1][1]);
116+
} else {
117+
$this->assertCount(0, $methodCalls);
118+
}
119+
}
120+
121+
public function getSuccessHandlers()
122+
{
123+
return array(
124+
array('security.authentication.success_handler.foo.abstract_factory', null, true),
125+
array('custom_success_handler_default', 'custom_success_handler_default', true),
126+
array('custom_success_handler', 'custom_success_handler', false),
127+
);
71128
}
72129

73130
protected function callFactory($id, $config, $userProviderId, $defaultEntryPointId)
@@ -92,11 +149,12 @@ protected function callFactory($id, $config, $userProviderId, $defaultEntryPoint
92149

93150
$container = new ContainerBuilder();
94151
$container->register('auth_provider');
152+
$container->register('custom_success_handler');
153+
$container->register('custom_failure_handler');
154+
$container->setDefinition('custom_success_handler_default', new DefinitionDecorator('security.authentication.success_handler'));
155+
$container->setDefinition('custom_failure_handler_default', new DefinitionDecorator('security.authentication.failure_handler'));
95156

96-
list($authProviderId,
97-
$listenerId,
98-
$entryPointId
99-
) = $factory->create($container, $id, $config, $userProviderId, $defaultEntryPointId);
157+
list($authProviderId, $listenerId, $entryPointId) = $factory->create($container, $id, $config, $userProviderId, $defaultEntryPointId);
100158

101159
return array($container, $authProviderId, $listenerId, $entryPointId);
102160
}

src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/StandardFormLogin/localized_form_failure_h D375 andler.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
imports:
22
- { resource: ./../config/default.yml }
33

4+
services:
5+
localized_form_failure_handler: { class: stdClass }
6+
47
security:
58
encoders:
69
Symfony\Component\Security\Core\User\User: plaintext

src/Symfony/Component/Security/Http/Authentication/DefaultAuthenticationFailureHandler.php

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,12 @@ class DefaultAuthenticationFailureHandler implements AuthenticationFailureHandle
3434
protected $httpUtils;
3535
protected $logger;
3636
protected $options;
37+
protected $defaultOptions = array(
38+
'failure_path' => null,
39+
'failure_forward' => false,
40+
'login_path' => '/login',
41+
'failure_path_parameter' => '_failure_path',
42+
);
3743

3844
/**
3945
* Constructor.
@@ -43,18 +49,32 @@ class DefaultAuthenticationFailureHandler implements AuthenticationFailureHandle
4349
* @param array $options Options for processing a failed authentication attempt.
4450
* @param LoggerInterface $logger Optional logger
4551
*/
46-
public function __construct(HttpKernelInterface $httpKernel, HttpUtils $httpUtils, array $options, LoggerInterface $logger = null)
52+
public function __construct(HttpKernelInterface $httpKernel, HttpUtils $httpUtils, array $options = array(), LoggerInterface $logger = null)
4753
{
4854
$this->httpKernel = $httpKernel;
49-
$this->httpUtils = $httpUtils;
50-
$this->logger = $logger;
55+
$this->httpUtils = $httpUtils;
56+
$this->logger = $logger;
57+
$this->setOptions($options);
58+
}
5159

52-
$this->options = array_merge(array(
53-
'failure_path' => null,
54-
'failure_forward' => false,
55-
'login_path' => '/login',
56-
'failure_path_parameter' => '_failure_path',
57-
), $options);
60+
/**
61+
* Gets the options.
62+
*
63+
* @return array An array of options
64+
*/
65+
public function getOptions()
66+
{
67+
return $this->options;
68+
}
69+
70+
/**
71+
* Sets the options.
72+
*
73+
* @param array $options An array of options
74+
*/
75+
public function setOptions(array $options)
76+
{
77+
$this->options = array_merge($this->defaultOptions, $options);
5878
}
5979

6080
/**

src/Symfony/Component/Security/Http/Authentication/DefaultAuthenticationSuccessHandler.php

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,24 +27,24 @@ class DefaultAuthenticationSuccessHandler implements AuthenticationSuccessHandle
2727
protected $httpUtils;
2828
protected $options;
2929
protected $providerKey;
30+
protected $defaultOptions = < 384B span class=pl-en>array(
31+
'always_use_default_target_path' => false,
32+
'default_target_path' => '/',
33+
'login_path' => '/login',
34+
'target_path_parameter' => '_target_path',
35+
'use_referer' => false,
36+
);
3037

3138
/**
3239
* Constructor.
3340
*
3441
* @param HttpUtils $httpUtils
3542
* @param array $options Options for processing a successful authentication attempt.
3643
*/
37-
public function __construct(HttpUtils $httpUtils, array $options)
44+
public function __construct(HttpUtils $httpUtils, array $options = array())
3845
{
39-
$this->httpUtils = $httpUtils;
40-
41-
$this->options = array_merge(array(
42-
'always_use_default_target_path' => false,
43-
'default_target_path' => '/',
44-
'login_path' => '/login',
45-
'target_path_parameter' => '_target_path',
46-
'use_referer' => false,
47-
), $options);
46+
$this->httpUtils = $httpUtils;
47+
$this->setOptions($options);
4848
}
4949

5050
/**
@@ -55,6 +55,26 @@ public function onAuthenticationSuccess(Request $request, TokenInterface $token)
5555
return $this->httpUtils->createRedirectResponse($request, $this->determineTargetUrl($request));
5656
}
5757

58+
/**
59+
* Gets the options.
60+
*
61+
* @return array An array of options
62+
*/
63+
public function getOptions()
64+
{
65+
return $this->options;
66+
}
67+
68+
/**
69+
* Sets the options.
70+
*
71+
* @param array $options An array of options
72+
*/
73+
public function setOptions(array $options)
74+
{
75+
$this->options = array_merge($this->defaultOptions, $options);
76+
}
77+
5878
/**
5979
* Get the provider key.
6080
*

0 commit comments

Comments
 (0)
0