[Security] made sure that the exception listener is always removed from the event dispatcher at the end of the request

This commit is contained in:
Fabien Potencier 2013-09-08 15:07:37 +02:00
parent b1a062d232
commit 1b2ef74a9a
3 changed files with 30 additions and 7 deletions

View File

@ -13,6 +13,7 @@ namespace Symfony\Component\Security\Http;
use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\Event\FinishRequestEvent;
use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface;
@ -30,6 +31,7 @@ class Firewall implements EventSubscriberInterface
{ {
private $map; private $map;
private $dispatcher; private $dispatcher;
private $exceptionListeners;
/** /**
* Constructor. * Constructor.
@ -41,6 +43,7 @@ class Firewall implements EventSubscriberInterface
{ {
$this->map = $map; $this->map = $map;
$this->dispatcher = $dispatcher; $this->dispatcher = $dispatcher;
$this->exceptionListeners = new \SplObjectStorage();
} }
/** /**
@ -57,6 +60,7 @@ class Firewall implements EventSubscriberInterface
// register listeners for this firewall // register listeners for this firewall
list($listeners, $exception) = $this->map->getListeners($event->getRequest()); list($listeners, $exception) = $this->map->getListeners($event->getRequest());
if (null !== $exception) { if (null !== $exception) {
$this->exceptionListeners[$event->getRequest()] = $exception;
$exception->register($this->dispatcher); $exception->register($this->dispatcher);
} }
@ -70,8 +74,21 @@ class Firewall implements EventSubscriberInterface
} }
} }
public function onKernelFinishRequest(FinishRequestEvent $event)
{
$request = $event->getRequest();
if (isset($this->exceptionListeners[$request])) {
$this->exceptionListeners[$request]->unregister($this->dispatcher);
unset($this->exceptionListeners[$request]);
}
}
public static function getSubscribedEvents() public static function getSubscribedEvents()
{ {
return array(KernelEvents::REQUEST => array('onKernelRequest', 8)); return array(
KernelEvents::REQUEST => array('onKernelRequest', 8),
KernelEvents::FINISH_REQUEST => 'onKernelFinishRequest',
);
} }
} }

View File

@ -69,6 +69,16 @@ class ExceptionListener
$dispatcher->addListener(KernelEvents::EXCEPTION, array($this, 'onKernelException')); $dispatcher->addListener(KernelEvents::EXCEPTION, array($this, 'onKernelException'));
} }
/**
* Unregisters the dispatcher.
*
* @param EventDispatcherInterface $dispatcher An EventDispatcherInterface instance
*/
public function unregister(EventDispatcherInterface $dispatcher)
{
$dispatcher->removeListener(KernelEvents::EXCEPTION, array($this, 'onKernelException'));
}
/** /**
* Handles security related exceptions. * Handles security related exceptions.
* *
@ -76,10 +86,6 @@ class ExceptionListener
*/ */
public function onKernelException(GetResponseForExceptionEvent $event) public function onKernelException(GetResponseForExceptionEvent $event)
{ {
// we need to remove ourselves as the exception listener can be
// different depending on the Request
$event->getDispatcher()->removeListener(KernelEvents::EXCEPTION, array($this, 'onKernelException'));
$exception = $event->getException(); $exception = $event->getException();
$request = $event->getRequest(); $request = $event->getRequest();

View File

@ -18,8 +18,8 @@
"require": { "require": {
"php": ">=5.3.3", "php": ">=5.3.3",
"symfony/event-dispatcher": "~2.1", "symfony/event-dispatcher": "~2.1",
"symfony/http-foundation": "~2.1", "symfony/http-foundation": "~2.4",
"symfony/http-kernel": "~2.1" "symfony/http-kernel": "~2.4"
}, },
"require-dev": { "require-dev": {
"symfony/form": "~2.0", "symfony/form": "~2.0",