Skip to content
This repository was archived by the owner on May 31, 2024. It is now read-only.

Commit 94c2e30

Browse files
committed
bug #13466 [Security] Remove ContextListener's onKernelResponse listener as it is used (davedevelopment)
This PR was squashed before being merged into the 2.3 branch (closes #13466). Discussion ---------- [Security] Remove ContextListener's onKernelResponse listener as it is used | Q | A | ------------- | --- | Bug fix? | yes | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | | License | MIT | Doc PR | The context listeners are specific to a particular firewall, and as such, should not be applied if the current request doesn't match that context listener. To avoid this, the context listener can remove itself from the dispatcher as it is called. This comes in to affect when two or more firewalls are setup and using the same kernel for multiple requests. Assuming there are two firewalls 'site' and 'admin' - Request comes in matching 'site' firewall, 'site' ContextListener adds it's onKernelResponse method to the dispatcher - Succesful auth for 'site' - ContextListener writes token to session - Request comes in matching 'admin' firewall, 'admin' ContextListener can't find anything in the session, so nulls the token in the security context - 'site' ContextListener listens for response, can't find a token in the security context so removes the 'site' token from the session Commits ------- 380d805 [Security] Remove ContextListener's onKernelResponse listener as it is used
2 parents ad78f5a + ac536c3 commit 94c2e30

File tree

2 files changed

+36
-3
lines changed

2 files changed

+36
-3
lines changed

Http/Firewall/ContextListener.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,9 @@ public function onKernelResponse(FilterResponseEvent $event)
114114
return;
115115
}
116116

117+
$this->dispatcher->removeListener(KernelEvents::RESPONSE, array($this, 'onKernelResponse'));
118+
$this->registered = false;
119+
117120
if (null !== $this->logger) {
118121
$this->logger->debug('Write SecurityContext in the session');
119122
}

Tests/Http/Firewall/ContextListenerTest.php

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
2222
use Symfony\Component\Security\Core\SecurityContext;
2323
use Symfony\Component\Security\Http\Firewall\ContextListener;
24+
use Symfony\Component\EventDispatcher\EventDispatcher;
2425

2526
class ContextListenerTest extends \PHPUnit_Framework_TestCase
2627
{
@@ -111,7 +112,7 @@ public function testOnKernelResponseWithoutSession()
111112
new Response()
112113
);
113114

114-
$listener = new ContextListener($this->securityContext, array(), 'session');
115+
$listener = new ContextListener($this->securityContext, array(), 'session', null, new EventDispatcher());
115116
$listener->onKernelResponse($event);
116117

117118
$this->assertTrue($session->isStarted());
@@ -130,7 +131,7 @@ public function testOnKernelResponseWithoutSessionNorToken()
130131
new Response()
131132
);
132133

133-
$listener = new ContextListener($this->securityContext, array(), 'session');
134+
$listener = new ContextListener($this->securityContext, array(), 'session', null, new EventDispatcher());
134135
$listener->onKernelResponse($event);
135136

136137
$this->assertFalse($session->isStarted());
@@ -202,6 +203,35 @@ public function testHandleAddsKernelResponseListener()
202203
$listener->handle($event);
203204
}
204205

206+
public function testOnKernelResponseListenerRemovesItself()
207+
{
208+
$context = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface');
209+
$dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface');
210+
$event = $this->getMockBuilder('Symfony\Component\HttpKernel\Event\FilterResponseEvent')
211+
->disableOriginalConstructor()
212+
->getMock();
213+
214+
$listener = new ContextListener($context, array(), 'key123', null, $dispatcher);
215+
216+
$request = $this->getMock('Symfony\Component\HttpFoundation\Request');
217+
$request->expects($this->any())
218+
->method('hasSession')
219+
->will($this->returnValue(true));
220+
221+
$event->expects($this->any())
222+
->method('getRequestType')
223+
->will($this->returnValue(HttpKernelInterface::MASTER_REQUEST));
224+
$event->expects($this->any())
225+
->method('getRequest')
226+
->will($this->returnValue($request));
227+
228+
$dispatcher->expects($this->once())
229+
->method('removeListener')
230+
->with(KernelEvents::RESPONSE, array($listener, 'onKernelResponse'));
231+
232+
$listener->onKernelResponse($event);
233+
}
234+
205235
public function testHandleRemovesTokenIfNoPreviousSessionWasFound()
206236
{
207237
$request = $this->getMock('Symfony\Component\HttpFoundation\Request');
@@ -240,7 +270,7 @@ protected function runSessionOnKernelResponse($newToken, $original = null)
240270
new Response()
241271
);
242272

243-
$listener = new ContextListener($this->securityContext, array(), 'session');
273+
$listener = new ContextListener($this->securityContext, array(), 'session', null, new EventDispatcher());
244274
$listener->onKernelResponse($event);
245275

246276
return $session;

0 commit comments

Comments
 (0)