Skip to content

Commit

Permalink
[Security] adds logout success handler
Browse files Browse the repository at this point in the history
  • Loading branch information
schmittjoh authored and fabpot committed Feb 14, 2011
1 parent bc283f1 commit b685b3a
Show file tree
Hide file tree
Showing 6 changed files with 55 additions and 7 deletions.
Expand Up @@ -141,6 +141,7 @@ protected function addFirewallsSection($rootNode, array $factories)
->canBeUnset()
->scalarNode('path')->defaultValue('/logout')->end()
->scalarNode('target')->defaultValue('/')->end()
->scalarNode('success_handler')->end()
->booleanNode('invalidate_session')->defaultTrue()->end()
->fixXmlConfig('delete_cookie')
->arrayNode('delete_cookies')
Expand Down
Expand Up @@ -243,10 +243,15 @@ protected function createFirewall(ContainerBuilder $container, $id, $firewall, &
if (isset($firewall['logout'])) {
$listenerId = 'security.logout_listener.'.$id;
$listener = $container->setDefinition($listenerId, new DefinitionDecorator('security.logout_listener'));
$listener->addArgument($firewall['logout']['path']);
$listener->addArgument($firewall['logout']['target']);
$listener->setArgument(1, $firewall['logout']['path']);
$listener->setArgument(2, $firewall['logout']['target']);
$listeners[] = new Reference($listenerId);

// add logout success handler
if (isset($firewall['logout']['success_handler'])) {
$listener->setArgument(3, new Reference($firewall['logout']['success_handler']));
}

// add session logout handler
if (true === $firewall['logout']['invalidate_session'] && false === $firewall['stateless']) {
$listener->addMethodCall('addHandler', array(new Reference('security.logout.handler.session')));
Expand Down
Expand Up @@ -84,6 +84,9 @@

<service id="security.logout_listener" class="%security.logout_listener.class%" public="false" abstract="true">
<argument type="service" id="security.context" />
<argument /> <!-- Logout Path -->
<argument /> <!-- Target-URL Path -->
<argument type="service" id="security.logout.success_handler" on-invalid="null" />
</service>
<service id="security.logout.handler.session" class="%security.logout.handler.session.class%" public="false" />
<service id="security.logout.handler.cookie_clearing" class="%security.logout.handler.cookie_clearing.class%" public="false" abstract="true" />
Expand Down
2 changes: 0 additions & 2 deletions src/Symfony/Bundle/SecurityBundle/SecurityBundle.php
Expand Up @@ -13,7 +13,6 @@

use Symfony\Component\HttpKernel\Bundle\Bundle;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Bundle\SecurityBundle\DependencyInjection\Compiler\AddAuthenticationProvidersPass;
use Symfony\Bundle\SecurityBundle\DependencyInjection\Compiler\AddSecurityVotersPass;

/**
Expand All @@ -28,6 +27,5 @@ public function registerExtensions(ContainerBuilder $container)
parent::registerExtensions($container);

$container->addCompilerPass(new AddSecurityVotersPass());
$container->addCompilerPass(new AddAuthenticationProvidersPass());
}
}
18 changes: 15 additions & 3 deletions src/Symfony/Component/Security/Http/Firewall/LogoutListener.php
Expand Up @@ -11,6 +11,8 @@

namespace Symfony\Component\Security\Http\Firewall;

use Symfony\Component\Security\Http\Logout\LogoutSuccessHandlerInterface;

use Symfony\Component\Security\Http\Logout\LogoutHandlerInterface;
use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
Expand All @@ -28,6 +30,7 @@ class LogoutListener implements ListenerInterface
protected $logoutPath;
protected $targetUrl;
protected $handlers;
protected $successHandler;

/**
* Constructor
Expand All @@ -36,11 +39,12 @@ class LogoutListener implements ListenerInterface
* @param string $logoutPath The path that starts the logout process
* @param string $targetUrl The URL to redirect to after logout
*/
public function __construct(SecurityContextInterface $securityContext, $logoutPath, $targetUrl = '/')
public function __construct(SecurityContextInterface $securityContext, $logoutPath, $targetUrl = '/', LogoutSuccessHandlerInterface $successHandler = null)
{
$this->securityContext = $securityContext;
$this->logoutPath = $logoutPath;
$this->targetUrl = $targetUrl;
$this->successHandler = $successHandler;
$this->handlers = array();
}

Expand Down Expand Up @@ -86,8 +90,16 @@ public function handle(EventInterface $event)
return;
}

$response = new Response();
$response->setRedirect(0 !== strpos($this->targetUrl, 'http') ? $request->getUriForPath($this->targetUrl) : $this->targetUrl, 302);
if (null !== $this->successHandler) {
$response = $this->successHandler->onLogoutSuccess($event, $request);

if (!$response instanceof Response) {
throw new \RuntimeException('Logout Success Handler did not return a Response.');
}
} else {
$response = new Response();
$response->setRedirect(0 !== strpos($this->targetUrl, 'http') ? $request->getUriForPath($this->targetUrl) : $this->targetUrl, 302);
}

// handle multiple logout attempts gracefully
if ($token = $this->securityContext->getToken()) {
Expand Down
@@ -0,0 +1,29 @@
<?php

namespace Symfony\Component\Security\Http\Logout;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\EventDispatcher\EventInterface;

/**
* LogoutSuccesshandlerInterface.
*
* In contrast to the LogoutHandlerInterface, this interface can return a response
* which is then used instead of the default behavior.
*
* If you want to only perform some logout related clean-up task, use the
* LogoutHandlerInterface instead.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
interface LogoutSuccessHandlerInterface
{
/**
* Creates a Response object to send upon a successful logout.
*
* @param EventInterface $event
* @param Request $request
* @return Response never null
*/
function onLogoutSuccess(EventInterface $event, Request $request);
}

0 comments on commit b685b3a

Please sign in to comment.