Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 9e88eb5

Browse files
MatTheCatnicolas-grekas
authored andcommitted
[Security] Fix logout
1 parent b7feafc commit 9e88eb5

File tree

12 files changed

+119
-23
lines changed

12 files changed

+119
-23
lines changed

src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -222,13 +222,14 @@ private function createFirewalls($config, ContainerBuilder $container)
222222
$mapDef = $container->getDefinition('security.firewall.map');
223223
$map = $authenticationProviders = array();
224224
foreach ($firewalls as $name => $firewall) {
225-
list($matcher, $listeners, $exceptionListener) = $this->createFirewall($container, $name, $firewall, $authenticationProviders, $providerIds);
225+
list($matcher, $listeners, $exceptionListener, $logoutListener) = $this->createFirewall($container, $name, $firewall, $authenticationProviders, $providerIds);
226226

227227
$contextId = 'security.firewall.map.context.'.$name;
228228
$context = $container->setDefinition($contextId, new DefinitionDecorator('security.firewall.context'));
229229
$context
230230
->replaceArgument(0, $listeners)
231231
->replaceArgument(1, $exceptionListener)
232+
->replaceArgument(2, $logoutListener)
232233
;
233234
$map[$contextId] = $matcher;
234235
}
@@ -259,7 +260,7 @@ private function createFirewall(ContainerBuilder $container, $id, $firewall, &$a
259260

260261
// Security disabled?
261262
if (false === $firewall['security']) {
262-
return array($matcher, array(), null);
263+
return array($matcher, array(), null, null);
263264
}
264265

265266
// Provider id (take the first registered provider if none defined)
@@ -286,15 +287,15 @@ private function createFirewall(ContainerBuilder $container, $id, $firewall, &$a
286287
}
287288

288289
// Logout listener
290+
$logoutListenerId = null;
289291
if (isset($firewall['logout'])) {
290-
$listenerId = 'security.logout_listener.'.$id;
291-
$listener = $container->setDefinition($listenerId, new DefinitionDecorator('security.logout_listener'));
292-
$listener->replaceArgument(3, array(
292+
$logoutListenerId = 'security.logout_listener.'.$id;
293+
$logoutListener = $container->setDefinition($logoutListenerId, new DefinitionDecorator('security.logout_listener'));
294+
$logoutListener->replaceArgument(3, array(
293295
'csrf_parameter' => $firewall['logout']['csrf_parameter'],
294296
'intention' => $firewall['logout']['csrf_token_id'],
295297
'logout_path' => $firewall['logout']['path'],
296298
));
297-
$listeners[] = new Reference($listenerId);
298299

299300
// add logout success handler
300301
if (isset($firewall['logout']['success_handler'])) {
@@ -304,16 +305,16 @@ private function createFirewall(ContainerBuilder $container, $id, $firewall, &$a
304305
$logoutSuccessHandler = $container->setDefinition($logoutSuccessHandlerId, new DefinitionDecorator('security.logout.success_handler'));
305306
$logoutSuccessHandler->replaceArgument(1, $firewall['logout']['target']);
306307
}
307-
$listener->replaceArgument(2, new Reference($logoutSuccessHandlerId));
308+
$logoutListener->replaceArgument(2, new Reference($logoutSuccessHandlerId));
308309

309310
// add CSRF provider
310311
if (isset($firewall['logout']['csrf_token_generator'])) {
311-
$listener->addArgument(new Reference($firewall['logout']['csrf_token_generator']));
312+
$logoutListener->addArgument(new Reference($firewall['logout']['csrf_token_generator']));
312313
}
313314

314315
// add session logout handler
315316
if (true === $firewall['logout']['invalidate_session'] && false === $firewall['stateless']) {
316-
$listener->addMethodCall('addHandler', array(new Reference('security.logout.handler.session')));
317+
$logoutListener->addMethodCall('addHandler', array(new Reference('security.logout.handler.session')));
317318
}
318319

319320
// add cookie logout handler
@@ -322,12 +323,12 @@ private function createFirewall(ContainerBuilder $container, $id, $firewall, &$a
322323
$cookieHandler = $container->setDefinition($cookieHandlerId, new DefinitionDecorator('security.logout.handler.cookie_clearing'));
323324
$cookieHandler->addArgument($firewall['logout']['delete_cookies']);
324325

325-
$listener->addMethodCall('addHandler', array(new Reference($cookieHandlerId)));
326+
$logoutListener->addMethodCall('addHandler', array(new Reference($cookieHandlerId)));
326327
}
327328

328329
// add custom handlers
329330
foreach ($firewall['logout']['handlers'] as $handlerId) {
330-
$listener->addMethodCall('addHandler', array(new Reference($handlerId)));
331+
$logoutListener->addMethodCall('addHandler', array(new Reference($handlerId)));
331332
}
332333

333334
// register with LogoutUrlGenerator
@@ -362,7 +363,7 @@ private function createFirewall(ContainerBuilder $container, $id, $firewall, &$a
362363
// Exception listener
363364
$exceptionListener = new Reference($this->createExceptionListener($container, $firewall, $id, $configuredEntryPoint ?: $defaultEntryPoint, $firewall['stateless']));
364365

365-
return array($matcher, $listeners, $exceptionListener);
366+
return array($matcher, $listeners, $exceptionListener, null !== $logoutListenerId ? new Reference($logoutListenerId) : null);
366367
}
367368

368369
private function createContextListener($container, $contextKey)

src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@
150150
<service id="security.firewall.context" class="%security.firewall.context.class%" abstract="true">
151151
<argument type="collection" />
152152
<argument type="service" id="security.exception_listener" />
153+
<argument /> <!-- LogoutListener -->
153154
</service>
154155

155156
<service id="security.logout_url_generator" class="Symfony\Component\Security\Http\Logout\LogoutUrlGenerator" public="false">

src/Symfony/Bundle/SecurityBundle/Security/FirewallContext.php

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

1414
use Symfony\Component\Security\Http\Firewall\ExceptionListener;
15+
use Symfony\Component\Security\Http\Firewall\LogoutListener;
1516

1617
/**
1718
* This is a wrapper around the actual firewall configuration which allows us
@@ -23,15 +24,17 @@ class FirewallContext
2324
{
2425
private $listeners;
2526
private $exceptionListener;
27+
private $logoutListener;
2628

27-
public function __construct(array $listeners, ExceptionListener $exceptionListener = null)
29+
public function __construct(array $listeners, ExceptionListener $exceptionListener = null, LogoutListener $logoutListener = null)
2830
{
2931
$this->listeners = $listeners;
3032
$this->exceptionListener = $exceptionListener;
33+
$this->logoutListener = $logoutListener;
3134
}
3235

3336
public function getContext()
3437
{
35-
return array($this->listeners, $this->exceptionListener);
38+
return array($this->listeners, $this->exceptionListener, $this->logoutListener);
3639
}
3740
}

src/Symfony/Bundle/SecurityBundle/Security/FirewallMap.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,6 @@ public function getListeners(Request $request)
4141
}
4242
}
4343

44-
return array(array(), null);
44+
return array(array(), null, null);
4545
}
4646
}

src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,6 @@ public function testFirewalls()
7676
array(),
7777
array(
7878
'security.channel_listener',
79-
'security.logout_listener.secure',
8079
'security.authentication.listener.x509.secure',
8180
'security.authentication.listener.remote_user.secure',
8281
'security.authentication.listener.form.secure',
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bundle\SecurityBundle\Tests\Functional;
13+
14+
class LogoutTest extends WebTestCase
15+
{
16+
public function testSessionLessRememberMeLogout()
17+
{
18+
$client = $this->createClient(array('test_case' => 'RememberMeLogout', 'root_config' => 'config.yml'));
19+
20+
$client->request('POST', '/login', array(
21+
'_username' => 'johannes',
22+
'_password' => 'test',
23+
));
24+
25+
$cookieJar = $client->getCookieJar();
26+
$cookieJar->expire(session_name());
27+
28+
$this->assertNotNull($cookieJar->get('REMEMBERME'));
29+
30+
$client->request('GET', '/logout');
31+
32+
$this->assertNull($cookieJar->get('REMEMBERME'));
33+
}
34+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
use Symfony\Bundle\SecurityBundle\SecurityBundle;
13+
use Symfony\Bundle\FrameworkBundle\FrameworkBundle;
14+
15+
return array(
16+
new FrameworkBundle(),
17+
new SecurityBundle(),
18+
);
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
imports:
2+
- { resource: ./../config/framework.yml }
3+
4+
security:
5+
encoders:
6+
Symfony\Component\Security\Core\User\User: plaintext
7+
8+
providers:
9+
in_memory:
10+
memory:
11+
users:
12+
johannes: { password: test, roles: [ROLE_USER] }
13+
14+
firewalls:
15+
default:
16+
form_login:
17+
check_path: login
18+
remember_me: true
19+
require_previous_session: false
20+
remember_me:
21+
always_remember_me: true
22+
key: key
23+
logout: ~
24+
anonymous: ~
25+
stateless: true
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
login:
2+
path: /login
3+
4+
logout:
5+
path: /logout

src/Symfony/Bundle/SecurityBundle/composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
"require": {
1919
"php": ">=5.3.9",
2020
"ext-xml": "*",
21-
"symfony/security": "~2.7.38|~2.8.31",
21+
"symfony/security": "~2.7.47|~2.8.40",
2222
"symfony/security-acl": "~2.7",
2323
"symfony/http-kernel": "~2.7"
2424
},

src/Symfony/Component/Security/Http/Firewall.php

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,20 +47,29 @@ public function onKernelRequest(GetResponseEvent $event)
4747
}
4848

4949
// register listeners for this firewall
50-
list($listeners, $exceptionListener) = $this->map->getListeners($event->getRequest());
50+
$listeners = $this->map->getListeners($event->getRequest());
51+
52+
$authenticationListeners = $listeners[0];
53+
$exceptionListener = $listeners[1];
54+
$logoutListener = isset($listeners[2]) ? $listeners[2] : null;
55+
5156
if (null !== $exceptionListener) {
5257
$this->exceptionListeners[$event->getRequest()] = $exceptionListener;
5358
$exceptionListener->register($this->dispatcher);
5459
}
5560

5661
// initiate the listener chain
57-
foreach ($listeners as $listener) {
62+
foreach ($authenticationListeners as $listener) {
5863
$listener->handle($event);
5964

6065
if ($event->hasResponse()) {
6166
break;
6267
}
6368
}
69+
70+
if (null !== $logoutListener) {
71+
$logoutListener->handle($event);
72+
}
6473
}
6574

6675
public function onKernelFinishRequest(FinishRequestEvent $event)

src/Symfony/Component/Security/Http/FirewallMap.php

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use Symfony\Component\HttpFoundation\RequestMatcherInterface;
1515
use Symfony\Component\HttpFoundation\Request;
1616
use Symfony\Component\Security\Http\Firewall\ExceptionListener;
17+
use Symfony\Component\Security\Http\Firewall\LogoutListener;
1718

1819
/**
1920
* FirewallMap allows configuration of different firewalls for specific parts
@@ -25,9 +26,9 @@ class FirewallMap implements FirewallMapInterface
2526
{
2627
private $map = array();
2728

28-
public function add(RequestMatcherInterface $requestMatcher = null, array $listeners = array(), ExceptionListener $exceptionListener = null)
29+
public function add(RequestMatcherInterface $requestMatcher = null, array $listeners = array(), ExceptionListener $exceptionListener = null, LogoutListener $logoutListener = null)
2930
{
30-
$this->map[] = array($requestMatcher, $listeners, $exceptionListener);
31+
$this->map[] = array($requestMatcher, $listeners, $exceptionListener, $logoutListener);
3132
}
3233

3334
/**
@@ -37,10 +38,10 @@ public function getListeners(Request $request)
3738
{
3839
foreach ($this->map as $elements) {
3940
if (null === $elements[0] || $elements[0]->matches($request)) {
40-
return array($elements[1], $elements[2]);
41+
return array($elements[1], $elements[2], $elements[3]);
4142
}
4243
}
4344

44-
return array(array(), null);
45+
return array(array(), null, null);
4546
}
4647
}

0 commit comments

Comments
 (0)