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.
*