diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml b/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml index c0c90439e1767..9a8df9416f105 100644 --- a/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml +++ b/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml @@ -71,7 +71,7 @@ - + @@ -107,6 +107,7 @@ + diff --git a/src/Symfony/Component/Security/Http/Firewall.php b/src/Symfony/Component/Security/Http/Firewall.php index f7fabbba43945..25f6d88b253a9 100644 --- a/src/Symfony/Component/Security/Http/Firewall.php +++ b/src/Symfony/Component/Security/Http/Firewall.php @@ -34,6 +34,7 @@ class Firewall protected $map; protected $dispatcher; protected $currentListeners; + protected $listenersStack; /** * Constructor. @@ -54,16 +55,14 @@ public function __construct(FirewallMapInterface $map, EventDispatcherInterface */ public function handle(EventInterface $event) { - if (HttpKernelInterface::MASTER_REQUEST !== $event->get('request_type')) { - return; - } - $request = $event->get('request'); // disconnect all listeners from core.security to avoid the overhead // of most listeners having to do this manually $this->dispatcher->disconnect('core.security'); + array_push($this->listenersStack, $this->currentListeners); + // ensure that listeners disconnect from wherever they have connected to foreach ($this->currentListeners as $listener) { $listener->unregister($this->dispatcher); @@ -92,4 +91,29 @@ public function handle(EventInterface $event) return $ret; } } + + /** + * Reconnects super request firewall listeners after finishing a sub request. + * + * All firewall listeners of the sub request are disconnected from all their + * events. + * + * @param EventInterface $event An EventInterface instance + */ + public function handleResponse(EventInterface $event) + { + $this->dispatcher->disconnect('core.security'); + + foreach ($this->currentListeners as $listener) { + $listener->unregister($this->dispatcher); + } + + $listeners = array_pop($this->listenersStack); + + if (null !== $listeners) { + foreach ($listeners as $listener) { + $listener->reconnect($this->dispatcher); + } + } + } } diff --git a/src/Symfony/Component/Security/Http/Firewall/AbstractAuthenticationListener.php b/src/Symfony/Component/Security/Http/Firewall/AbstractAuthenticationListener.php index 353185e218cca..dab33dffb64a0 100644 --- a/src/Symfony/Component/Security/Http/Firewall/AbstractAuthenticationListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/AbstractAuthenticationListener.php @@ -121,6 +121,13 @@ public function unregister(EventDispatcherInterface $dispatcher) { } + /** + * {@inheritDoc} + */ + public function reconnect(EventDispatcherInterface $dispatcher) + { + } + /** * Handles form based authentication. * diff --git a/src/Symfony/Component/Security/Http/Firewall/AbstractPreAuthenticatedListener.php b/src/Symfony/Component/Security/Http/Firewall/AbstractPreAuthenticatedListener.php index 555dadb2ceed5..e65ebf9d34922 100644 --- a/src/Symfony/Component/Security/Http/Firewall/AbstractPreAuthenticatedListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/AbstractPreAuthenticatedListener.php @@ -64,6 +64,13 @@ public function unregister(EventDispatcherInterface $dispatcher) { } + /** + * {@inheritDoc} + */ + public function reconnect(EventDispatcherInterface $dispatcher) + { + } + /** * Handles X509 authentication. * diff --git a/src/Symfony/Component/Security/Http/Firewall/AccessListener.php b/src/Symfony/Component/Security/Http/Firewall/AccessListener.php index 4aa1c552788d1..47b2e1aecd800 100644 --- a/src/Symfony/Component/Security/Http/Firewall/AccessListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/AccessListener.php @@ -53,7 +53,7 @@ public function register(EventDispatcherInterface $dispatcher) { $dispatcher->connect('core.security', array($this, 'handle'), 0); } - + /** * {@inheritDoc} */ @@ -61,6 +61,13 @@ public function unregister(EventDispatcherInterface $dispatcher) { } + /** + * {@inheritDoc} + */ + public function reconnect(EventDispatcherInterface $dispatcher) + { + } + /** * Handles access authorization. * diff --git a/src/Symfony/Component/Security/Http/Firewall/AnonymousAuthenticationListener.php b/src/Symfony/Component/Security/Http/Firewall/AnonymousAuthenticationListener.php index 05d23012e062c..b2fe133fbe6ad 100644 --- a/src/Symfony/Component/Security/Http/Firewall/AnonymousAuthenticationListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/AnonymousAuthenticationListener.php @@ -55,6 +55,13 @@ public function unregister(EventDispatcherInterface $dispatcher) { } + /** + * {@inheritDoc} + */ + public function reconnect(EventDispatcherInterface $dispatcher) + { + } + /** * Handles anonymous authentication. * diff --git a/src/Symfony/Component/Security/Http/Firewall/BasicAuthenticationListener.php b/src/Symfony/Component/Security/Http/Firewall/BasicAuthenticationListener.php index 972d081e77928..32acd15413fce 100644 --- a/src/Symfony/Component/Security/Http/Firewall/BasicAuthenticationListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/BasicAuthenticationListener.php @@ -66,6 +66,13 @@ public function unregister(EventDispatcherInterface $dispatcher) { } + /** + * {@inheritDoc} + */ + public function reconnect(EventDispatcherInterface $dispatcher) + { + } + /** * Handles basic authentication. * diff --git a/src/Symfony/Component/Security/Http/Firewall/ChannelListener.php b/src/Symfony/Component/Security/Http/Firewall/ChannelListener.php index 49cef7e35b95c..e4f2aa8872c03 100644 --- a/src/Symfony/Component/Security/Http/Firewall/ChannelListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/ChannelListener.php @@ -54,6 +54,13 @@ public function unregister(EventDispatcherInterface $dispatcher) { } + /** + * {@inheritDoc} + */ + public function reconnect(EventDispatcherInterface $dispatcher) + { + } + /** * Handles channel management. * diff --git a/src/Symfony/Component/Security/Http/Firewall/ContextListener.php b/src/Symfony/Component/Security/Http/Firewall/ContextListener.php index edc2f8cda5938..475995d7a0d15 100644 --- a/src/Symfony/Component/Security/Http/Firewall/ContextListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/ContextListener.php @@ -69,6 +69,14 @@ public function unregister(EventDispatcherInterface $dispatcher) $dispatcher->disconnect('core.response', array($this, 'write')); } + /** + * {@inheritDoc} + */ + public function reconnect(EventDispatcherInterface $dispatcher) + { + $dispatcher->connect('core.response', array($this, 'write'), 0); + } + /** * Reads the SecurityContext from the session. * diff --git a/src/Symfony/Component/Security/Http/Firewall/DigestAuthenticationListener.php b/src/Symfony/Component/Security/Http/Firewall/DigestAuthenticationListener.php index 490e409058deb..7f7684422894a 100644 --- a/src/Symfony/Component/Security/Http/Firewall/DigestAuthenticationListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/DigestAuthenticationListener.php @@ -69,6 +69,13 @@ public function unregister(EventDispatcherInterface $dispatcher) { } + /** + * {@inheritDoc} + */ + public function reconnect(EventDispatcherInterface $dispatcher) + { + } + /** * Handles digest authentication. * diff --git a/src/Symfony/Component/Security/Http/Firewall/ExceptionListener.php b/src/Symfony/Component/Security/Http/Firewall/ExceptionListener.php index 350b02905dac9..0ce069d369b67 100644 --- a/src/Symfony/Component/Security/Http/Firewall/ExceptionListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/ExceptionListener.php @@ -70,6 +70,14 @@ public function unregister(EventDispatcherInterface $dispatcher) $dispatcher->disconnect('core.exception', array($this, 'handleException')); } + /** + * {@inheritDoc} + */ + public function reconnect(EventDispatcherInterface $dispatcher) + { + $dispatcher->connect('core.exception', array($this, 'handleException'), 0); + } + /** * Handles security related exceptions. * diff --git a/src/Symfony/Component/Security/Http/Firewall/ListenerInterface.php b/src/Symfony/Component/Security/Http/Firewall/ListenerInterface.php index afb2d9f028c04..817a8522a0c32 100644 --- a/src/Symfony/Component/Security/Http/Firewall/ListenerInterface.php +++ b/src/Symfony/Component/Security/Http/Firewall/ListenerInterface.php @@ -15,7 +15,7 @@ /** * Interface that must be implemented by firewall listeners - * + * * @author Johannes M. Schmitt */ interface ListenerInterface @@ -39,4 +39,15 @@ function register(EventDispatcherInterface $dispatcher); * @param EventDispatcherInterface $dispatcher */ function unregister(EventDispatcherInterface $dispatcher); + + /** + * The implementation must reconnect this listener to all events it needs to + * handle after the core.security event. + * + * This method is called only if a sub request required the listeners to be + * unregistered. + * + * @param EventDispatcherInterface $dispatcher + */ + function reconnect(EventDispatcherInterface $dispatcher); } \ No newline at end of file diff --git a/src/Symfony/Component/Security/Http/Firewall/LogoutListener.php b/src/Symfony/Component/Security/Http/Firewall/LogoutListener.php index 1f5bc4524ce84..46a1b360f0d51 100644 --- a/src/Symfony/Component/Security/Http/Firewall/LogoutListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/LogoutListener.php @@ -78,6 +78,13 @@ public function unregister(EventDispatcherInterface $dispatcher) { } + /** + * {@inheritDoc} + */ + public function reconnect(EventDispatcherInterface $dispatcher) + { + } + /** * Performs the logout if requested * diff --git a/src/Symfony/Component/Security/Http/Firewall/RememberMeListener.php b/src/Symfony/Component/Security/Http/Firewall/RememberMeListener.php index db9b6232c33ee..41dbfc519e150 100644 --- a/src/Symfony/Component/Security/Http/Firewall/RememberMeListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/RememberMeListener.php @@ -76,6 +76,14 @@ public function unregister(EventDispatcherInterface $dispatcher) $dispatcher->disconnect('core.response', array($this, 'updateCookies')); } + /** + * {@inheritDoc} + */ + public function reconnect(EventDispatcherInterface $dispatcher) + { + $dispatcher->connect('core.response', array($this, 'updateCookies'), 0); + } + /** * Handles remember-me cookie based authentication. * diff --git a/src/Symfony/Component/Security/Http/Firewall/SwitchUserListener.php b/src/Symfony/Component/Security/Http/Firewall/SwitchUserListener.php index 4df51f0ed0ee0..d8d4bc8a1b73e 100644 --- a/src/Symfony/Component/Security/Http/Firewall/SwitchUserListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/SwitchUserListener.php @@ -85,6 +85,13 @@ public function unregister(EventDispatcherInterface $dispatcher) { } + /** + * {@inheritDoc} + */ + public function reconnect(EventDispatcherInterface $dispatcher) + { + } + /** * Handles digest authentication. *