diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php index 4ea9728eca..de1001aae6 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php @@ -279,18 +279,22 @@ class SecurityExtension extends Extension if (isset($firewall['logout'])) { $listenerId = 'security.logout_listener.'.$id; $listener = $container->setDefinition($listenerId, new DefinitionDecorator('security.logout_listener')); - $listener->replaceArgument(2, array( + $listener->replaceArgument(3, array( 'csrf_parameter' => $firewall['logout']['csrf_parameter'], 'intention' => $firewall['logout']['intention'], 'logout_path' => $firewall['logout']['path'], - 'target_url' => $firewall['logout']['target'], )); $listeners[] = new Reference($listenerId); // add logout success handler if (isset($firewall['logout']['success_handler'])) { - $listener->replaceArgument(3, new Reference($firewall['logout']['success_handler'])); + $logoutSuccessHandlerId = $firewall['logout']['success_handler']; + } else { + $logoutSuccessHandlerId = 'security.logout.success_handler.'.$id; + $logoutSuccessHandler = $container->setDefinition($logoutSuccessHandlerId, new DefinitionDecorator('security.logout.success_handler')); + $logoutSuccessHandler->replaceArgument(1, $firewall['logout']['target']); } + $listener->replaceArgument(2, new Reference($logoutSuccessHandlerId)); // add CSRF provider if (isset($firewall['logout']['csrf_provider'])) { diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/config/security_listeners.xml b/src/Symfony/Bundle/SecurityBundle/Resources/config/security_listeners.xml index 44644c9b3c..562ab94581 100644 --- a/src/Symfony/Bundle/SecurityBundle/Resources/config/security_listeners.xml +++ b/src/Symfony/Bundle/SecurityBundle/Resources/config/security_listeners.xml @@ -27,6 +27,7 @@ Symfony\Component\Security\Http\Firewall\LogoutListener Symfony\Component\Security\Http\Logout\SessionLogoutHandler Symfony\Component\Security\Http\Logout\CookieClearingLogoutHandler + Symfony\Component\Security\Http\Logout\DefaultLogoutSuccessHandler Symfony\Component\Security\Http\Firewall\AccessListener Symfony\Component\Security\Http\AccessMap @@ -84,12 +85,17 @@ + - + + + / + + diff --git a/src/Symfony/Component/Security/CHANGELOG.md b/src/Symfony/Component/Security/CHANGELOG.md index 797462b4e8..0093677c85 100644 --- a/src/Symfony/Component/Security/CHANGELOG.md +++ b/src/Symfony/Component/Security/CHANGELOG.md @@ -23,3 +23,5 @@ CHANGELOG * [BC BREAK] moved the default authentication success and failure handling to seperate classes. The order of arguments in the constructor of the `AbstractAuthenticationListener` has changed. + * [BC BREAK] moved the default logout sucess handling to a seperate class. The + order of arguments in the constructor of `LogoutListener` has changed. diff --git a/src/Symfony/Component/Security/Http/Firewall/LogoutListener.php b/src/Symfony/Component/Security/Http/Firewall/LogoutListener.php index d145fa17f6..32a0511307 100644 --- a/src/Symfony/Component/Security/Http/Firewall/LogoutListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/LogoutListener.php @@ -40,11 +40,11 @@ class LogoutListener implements ListenerInterface * * @param SecurityContextInterface $securityContext * @param HttpUtils $httpUtils An HttpUtilsInterface instance - * @param array $options An array of options to process a logout attempt * @param LogoutSuccessHandlerInterface $successHandler A LogoutSuccessHandlerInterface instance + * @param array $options An array of options to process a logout attempt * @param CsrfProviderInterface $csrfProvider A CsrfProviderInterface instance */ - public function __construct(SecurityContextInterface $securityContext, HttpUtils $httpUtils, array $options = array(), LogoutSuccessHandlerInterface $successHandler = null, CsrfProviderInterface $csrfProvider = null) + public function __construct(SecurityContextInterface $securityContext, HttpUtils $httpUtils, LogoutSuccessHandlerInterface $successHandler, array $options = array(), CsrfProviderInterface $csrfProvider = null) { $this->securityContext = $securityContext; $this->httpUtils = $httpUtils; @@ -52,7 +52,6 @@ class LogoutListener implements ListenerInterface 'csrf_parameter' => '_csrf_token', 'intention' => 'logout', 'logout_path' => '/logout', - 'target_url' => '/', ), $options); $this->successHandler = $successHandler; $this->csrfProvider = $csrfProvider; @@ -95,14 +94,9 @@ class LogoutListener implements ListenerInterface } } - if (null !== $this->successHandler) { - $response = $this->successHandler->onLogoutSuccess($request); - - if (!$response instanceof Response) { - throw new \RuntimeException('Logout Success Handler did not return a Response.'); - } - } else { - $response = $this->httpUtils->createRedirectResponse($request, $this->options['target_url']); + $response = $this->successHandler->onLogoutSuccess($request); + if (!$response instanceof Response) { + throw new \RuntimeException('Logout Success Handler did not return a Response.'); } // handle multiple logout attempts gracefully diff --git a/src/Symfony/Component/Security/Http/Logout/DefaultLogoutSuccessHandler.php b/src/Symfony/Component/Security/Http/Logout/DefaultLogoutSuccessHandler.php new file mode 100644 index 0000000000..e06cb6d089 --- /dev/null +++ b/src/Symfony/Component/Security/Http/Logout/DefaultLogoutSuccessHandler.php @@ -0,0 +1,47 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Security\Http\Logout; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\Security\Http\HttpUtils; +use Symfony\Component\Security\Http\Logout\LogoutSuccessHandlerInterface; + +/** + * Default logout success handler will redirect users to a configured path. + * + * @author Fabien Potencier + * @author Alexander + */ +class DefaultLogoutSuccessHandler implements LogoutSuccessHandlerInterface +{ + protected $httpUtils; + protected $targetUrl; + + /** + * @param HttpUtils $httpUtils + * @param string $targetUrl + */ + public function __construct(HttpUtils $httpUtils, $targetUrl = '/') + { + $this->httpUtils = $httpUtils; + + $this->targetUrl = $targetUrl; + } + + /** + * {@inheritDoc} + */ + public function onLogoutSuccess(Request $request) + { + return $this->httpUtils->createRedirectResponse($request, $this->targetUrl); + } +} diff --git a/src/Symfony/Component/Security/Tests/Http/Firewall/LogoutListenerTest.php b/src/Symfony/Component/Security/Tests/Http/Firewall/LogoutListenerTest.php index 6ffeed9797..aa0f5a7046 100644 --- a/src/Symfony/Component/Security/Tests/Http/Firewall/LogoutListenerTest.php +++ b/src/Symfony/Component/Security/Tests/Http/Firewall/LogoutListenerTest.php @@ -103,7 +103,9 @@ class LogoutListenerTest extends \PHPUnit_Framework_TestCase public function testHandleMatchedPathWithoutSuccessHandlerAndCsrfValidation() { - list($listener, $context, $httpUtils, $options) = $this->getListener(); + $successHandler = $this->getSuccessHandler(); + + list($listener, $context, $httpUtils, $options) = $this->getListener($successHandler); list($event, $request) = $this->getGetResponseEvent(); @@ -112,9 +114,9 @@ class LogoutListenerTest extends \PHPUnit_Framework_TestCase ->with($request, $options['logout_path']) ->will($this->returnValue(true)); - $httpUtils->expects($this->once()) - ->method('createRedirectResponse') - ->with($request, $options['target_url']) + $successHandler->expects($this->once()) + ->method('onLogoutSuccess') + ->with($request) ->will($this->returnValue($response = new Response())); $context->expects($this->once()) @@ -231,13 +233,13 @@ class LogoutListenerTest extends \PHPUnit_Framework_TestCase $listener = new LogoutListener( $context = $this->getContext(), $httpUtils = $this->getHttpUtils(), + $successHandler ?: $this->getSuccessHandler(), $options = array( 'csrf_parameter' => '_csrf_token', 'intention' => 'logout', 'logout_path' => '/logout', 'target_url' => '/', ), - $successHandler, $csrfProvider );