summaryrefslogtreecommitdiffstats
path: root/Http/Firewall
diff options
context:
space:
mode:
Diffstat (limited to 'Http/Firewall')
-rw-r--r--Http/Firewall/AbstractAuthenticationListener.php88
-rw-r--r--Http/Firewall/AccessListener.php4
-rw-r--r--Http/Firewall/ChannelListener.php4
-rw-r--r--Http/Firewall/ContextListener.php31
-rw-r--r--Http/Firewall/ExceptionListener.php26
-rw-r--r--Http/Firewall/LogoutListener.php72
-rw-r--r--Http/Firewall/RememberMeListener.php18
-rw-r--r--Http/Firewall/SwitchUserListener.php16
-rw-r--r--Http/Firewall/UsernamePasswordFormAuthenticationListener.php18
9 files changed, 139 insertions, 138 deletions
diff --git a/Http/Firewall/AbstractAuthenticationListener.php b/Http/Firewall/AbstractAuthenticationListener.php
index 8403ec7..410fb73 100644
--- a/Http/Firewall/AbstractAuthenticationListener.php
+++ b/Http/Firewall/AbstractAuthenticationListener.php
@@ -20,7 +20,6 @@ use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterfac
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Exception\SessionUnavailableException;
use Symfony\Component\HttpKernel\Log\LoggerInterface;
-use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
@@ -70,14 +69,14 @@ abstract class AbstractAuthenticationListener implements ListenerInterface
* @param SessionAuthenticationStrategyInterface $sessionStrategy
* @param HttpUtils $httpUtils An HttpUtilsInterface instance
* @param string $providerKey
+ * @param AuthenticationSuccessHandlerInterface $successHandler
+ * @param AuthenticationFailureHandlerInterface $failureHandler
* @param array $options An array of options for the processing of a
* successful, or failed authentication attempt
- * @param AuthenticationSuccessHandlerInterface $successHandler
- * @param AuthenticationFailureHandlerInterface $failureHandler
- * @param LoggerInterface $logger A LoggerInterface instance
- * @param EventDispatcherInterface $dispatcher An EventDispatcherInterface instance
+ * @param LoggerInterface $logger A LoggerInterface instance
+ * @param EventDispatcherInterface $dispatcher An EventDispatcherInterface instance
*/
- public function __construct(SecurityContextInterface $securityContext, AuthenticationManagerInterface $authenticationManager, SessionAuthenticationStrategyInterface $sessionStrategy, HttpUtils $httpUtils, $providerKey, array $options = array(), AuthenticationSuccessHandlerInterface $successHandler = null, AuthenticationFailureHandlerInterface $failureHandler = null, LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null)
+ public function __construct(SecurityContextInterface $securityContext, AuthenticationManagerInterface $authenticationManager, SessionAuthenticationStrategyInterface $sessionStrategy, HttpUtils $httpUtils, $providerKey, AuthenticationSuccessHandlerInterface $successHandler, AuthenticationFailureHandlerInterface $failureHandler, array $options = array(), LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null)
{
if (empty($providerKey)) {
throw new \InvalidArgumentException('$providerKey must not be empty.');
@@ -91,13 +90,6 @@ abstract class AbstractAuthenticationListener implements ListenerInterface
$this->failureHandler = $failureHandler;
$this->options = array_merge(array(
'check_path' => '/login_check',
- 'login_path' => '/login',
- 'always_use_default_target_path' => false,
- 'default_target_path' => '/',
- 'target_path_parameter' => '_target_path',
- 'use_referer' => false,
- 'failure_path' => null,
- 'failure_forward' => false,
), $options);
$this->logger = $logger;
$this->dispatcher = $dispatcher;
@@ -133,7 +125,7 @@ abstract class AbstractAuthenticationListener implements ListenerInterface
try {
if (!$request->hasPreviousSession()) {
- throw new SessionUnavailableException('Your session has timed-out, or you have disabled cookies.');
+ throw new SessionUnavailableException('Your session has timed out, or you have disabled cookies.');
}
if (null === $returnValue = $this->attemptAuthentication($request)) {
@@ -177,7 +169,7 @@ abstract class AbstractAuthenticationListener implements ListenerInterface
*
* @param Request $request A Request instance
*
- * @return TokenInterface The authenticated token, or null if full authentication is not possible
+ * @return TokenInterface|Response|null The authenticated token, null if full authentication is not possible, or a Response
*
* @throws AuthenticationException if the authentication fails
*/
@@ -191,32 +183,13 @@ abstract class AbstractAuthenticationListener implements ListenerInterface
$this->securityContext->setToken(null);
- if (null !== $this->failureHandler) {
- return $this->failureHandler->onAuthenticationFailure($request, $failed);
- }
-
- if (null === $this->options['failure_path']) {
- $this->options['failure_path'] = $this->options['login_path'];
- }
-
- if ($this->options['failure_forward']) {
- if (null !== $this->logger) {
- $this->logger->debug(sprintf('Forwarding to %s', $this->options['failure_path']));
- }
-
- $subRequest = $this->httpUtils->createRequest($request, $this->options['failure_path']);
- $subRequest->attributes->set(SecurityContextInterface::AUTHENTICATION_ERROR, $failed);
+ $response = $this->failureHandler->onAuthenticationFailure($request, $failed);
- return $event->getKernel()->handle($subRequest, HttpKernelInterface::SUB_REQUEST);
+ if (!$response instanceof Response) {
+ throw new \RuntimeException('Authentication Failure Handler did not return a Response.');
}
- if (null !== $this->logger) {
- $this->logger->debug(sprintf('Redirecting to %s', $this->options['failure_path']));
- }
-
- $request->getSession()->set(SecurityContextInterface::AUTHENTICATION_ERROR, $failed);
-
- return $this->httpUtils->createRedirectResponse($request, $this->options['failure_path']);
+ return $response;
}
private function onSuccess(GetResponseEvent $event, Request $request, TokenInterface $token)
@@ -236,10 +209,10 @@ abstract class AbstractAuthenticationListener implements ListenerInterface
$this->dispatcher->dispatch(SecurityEvents::INTERACTIVE_LOGIN, $loginEvent);
}
- if (null !== $this->successHandler) {
- $response = $this->successHandler->onAuthenticationSuccess($request, $token);
- } else {
- $response = $this->httpUtils->createRedirectResponse($request, $this->determineTargetUrl($request));
+ $response = $this->successHandler->onAuthenticationSuccess($request, $token);
+
+ if (!$response instanceof Response) {
+ throw new \RuntimeException('Authentication Success Handler did not return a Response.');
}
if (null !== $this->rememberMeServices) {
@@ -248,35 +221,4 @@ abstract class AbstractAuthenticationListener implements ListenerInterface
return $response;
}
-
- /**
- * Builds the target URL according to the defined options.
- *
- * @param Request $request
- *
- * @return string
- */
- private function determineTargetUrl(Request $request)
- {
- if ($this->options['always_use_default_target_path']) {
- return $this->options['default_target_path'];
- }
-
- if ($targetUrl = $request->get($this->options['target_path_parameter'], null, true)) {
- return $targetUrl;
- }
-
- $session = $request->getSession();
- if ($targetUrl = $session->get('_security.target_path')) {
- $session->remove('_security.target_path');
-
- return $targetUrl;
- }
-
- if ($this->options['use_referer'] && $targetUrl = $request->headers->get('Referer')) {
- return $targetUrl;
- }
-
- return $this->options['default_target_path'];
- }
}
diff --git a/Http/Firewall/AccessListener.php b/Http/Firewall/AccessListener.php
index 877b6c3..3e2d3a5 100644
--- a/Http/Firewall/AccessListener.php
+++ b/Http/Firewall/AccessListener.php
@@ -13,7 +13,7 @@ namespace Symfony\Component\Security\Http\Firewall;
use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;
-use Symfony\Component\Security\Http\AccessMap;
+use Symfony\Component\Security\Http\AccessMapInterface;
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
use Symfony\Component\HttpKernel\Log\LoggerInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
@@ -33,7 +33,7 @@ class AccessListener implements ListenerInterface
private $authManager;
private $logger;
- public function __construct(SecurityContextInterface $context, AccessDecisionManagerInterface $accessDecisionManager, AccessMap $map, AuthenticationManagerInterface $authManager, LoggerInterface $logger = null)
+ public function __construct(SecurityContextInterface $context, AccessDecisionManagerInterface $accessDecisionManager, AccessMapInterface $map, AuthenticationManagerInterface $authManager, LoggerInterface $logger = null)
{
$this->context = $context;
$this->accessDecisionManager = $accessDecisionManager;
diff --git a/Http/Firewall/ChannelListener.php b/Http/Firewall/ChannelListener.php
index 847753f..9b0f8c6 100644
--- a/Http/Firewall/ChannelListener.php
+++ b/Http/Firewall/ChannelListener.php
@@ -11,7 +11,7 @@
namespace Symfony\Component\Security\Http\Firewall;
-use Symfony\Component\Security\Http\AccessMap;
+use Symfony\Component\Security\Http\AccessMapInterface;
use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface;
use Symfony\Component\HttpKernel\Log\LoggerInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
@@ -28,7 +28,7 @@ class ChannelListener implements ListenerInterface
private $authenticationEntryPoint;
private $logger;
- public function __construct(AccessMap $map, AuthenticationEntryPointInterface $authenticationEntryPoint, LoggerInterface $logger = null)
+ public function __construct(AccessMapInterface $map, AuthenticationEntryPointInterface $authenticationEntryPoint, LoggerInterface $logger = null)
{
$this->map = $map;
$this->authenticationEntryPoint = $authenticationEntryPoint;
diff --git a/Http/Firewall/ContextListener.php b/Http/Firewall/ContextListener.php
index 6f267cf..b1ba24b 100644
--- a/Http/Firewall/ContextListener.php
+++ b/Http/Firewall/ContextListener.php
@@ -22,6 +22,7 @@ use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Component\Security\Core\User\UserInterface;
+use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
/**
@@ -36,6 +37,7 @@ class ContextListener implements ListenerInterface
private $contextKey;
private $logger;
private $userProviders;
+ private $dispatcher;
public function __construct(SecurityContextInterface $context, array $userProviders, $contextKey, LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null)
{
@@ -43,14 +45,17 @@ class ContextListener implements ListenerInterface
throw new \InvalidArgumentException('$contextKey must not be empty.');
}
+ foreach ($userProviders as $userProvider) {
+ if (!$userProvider instanceof UserProviderInterface) {
+ throw new \InvalidArgumentException(sprintf('User provider "%s" must implement "Symfony\Component\Security\Core\User\UserProviderInterface".', get_class($userProvider)));
+ }
+ }
+
$this->context = $context;
$this->userProviders = $userProviders;
$this->contextKey = $contextKey;
$this->logger = $logger;
-
- if (null !== $dispatcher) {
- $dispatcher->addListener(KernelEvents::RESPONSE, array($this, 'onKernelResponse'));
- }
+ $this->dispatcher = $dispatcher;
}
/**
@@ -60,6 +65,10 @@ class ContextListener implements ListenerInterface
*/
public function handle(GetResponseEvent $event)
{
+ if (null !== $this->dispatcher && HttpKernelInterface::MASTER_REQUEST === $event->getRequestType()) {
+ $this->dispatcher->addListener(KernelEvents::RESPONSE, array($this, 'onKernelResponse'));
+ }
+
$request = $event->getRequest();
$session = $request->hasPreviousSession() ? $request->getSession() : null;
@@ -103,19 +112,19 @@ class ContextListener implements ListenerInterface
return;
}
- if (null === $token = $this->context->getToken()) {
- return;
+ if (null !== $this->logger) {
+ $this->logger->debug('Write SecurityContext in the session');
}
- if (null === $token || $token instanceof AnonymousToken) {
+ if (null === $session = $event->getRequest()->getSession()) {
return;
}
- if (null !== $this->logger) {
- $this->logger->debug('Write SecurityContext in the session');
+ if ((null === $token = $this->context->getToken()) || ($token instanceof AnonymousToken)) {
+ $session->remove('_security_'.$this->contextKey);
+ } else {
+ $session->set('_security_'.$this->contextKey, serialize($token));
}
-
- $event->getRequest()->getSession()->set('_security_'.$this->contextKey, serialize($token));
}
/**
diff --git a/Http/Firewall/ExceptionListener.php b/Http/Firewall/ExceptionListener.php
index b704262..f134f9c 100644
--- a/Http/Firewall/ExceptionListener.php
+++ b/Http/Firewall/ExceptionListener.php
@@ -15,12 +15,12 @@ use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Http\Authorization\AccessDeniedHandlerInterface;
use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolverInterface;
-use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface;
use Symfony\Component\Security\Core\Exception\AccountStatusException;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use Symfony\Component\Security\Core\Exception\InsufficientAuthenticationException;
+use Symfony\Component\Security\Core\Exception\LogoutException;
use Symfony\Component\Security\Http\HttpUtils;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Log\LoggerInterface;
@@ -39,6 +39,7 @@ use Symfony\Component\EventDispatcher\EventDispatcherInterface;
class ExceptionListener
{
private $context;
+ private $providerKey;
private $accessDeniedHandler;
private $authenticationEntryPoint;
private $authenticationTrustResolver;
@@ -46,11 +47,12 @@ class ExceptionListener
private $logger;
private $httpUtils;
- public function __construct(SecurityContextInterface $context, AuthenticationTrustResolverInterface $trustResolver, HttpUtils $httpUtils, AuthenticationEntryPointInterface $authenticationEntryPoint = null, $errorPage = null, AccessDeniedHandlerInterface $accessDeniedHandler = null, LoggerInterface $logger = null)
+ public function __construct(SecurityContextInterface $context, AuthenticationTrustResolverInterface $trustResolver, HttpUtils $httpUtils, $providerKey, AuthenticationEntryPointInterface $authenticationEntryPoint = null, $errorPage = null, AccessDeniedHandlerInterface $accessDeniedHandler = null, LoggerInterface $logger = null)
{
$this->context = $context;
$this->accessDeniedHandler = $accessDeniedHandler;
$this->httpUtils = $httpUtils;
+ $this->providerKey = $providerKey;
$this->authenticationEntryPoint = $authenticationEntryPoint;
$this->authenticationTrustResolver = $trustResolver;
$this->errorPage = $errorPage;
@@ -95,10 +97,12 @@ class ExceptionListener
return;
}
} elseif ($exception instanceof AccessDeniedException) {
+ $event->setException(new AccessDeniedHttpException($exception->getMessage(), $exception));
+
$token = $this->context->getToken();
if (!$this->authenticationTrustResolver->isFullFledged($token)) {
if (null !== $this->logger) {
- $this->logger->debug('Access denied (user is not fully authenticated); redirecting to authentication entry point');
+ $this->logger->debug(sprintf('Access is denied (user is not fully authenticated) by "%s" at line %s; redirecting to authentication entry point', $exception->getFile(), $exception->getLine()));
}
try {
@@ -110,7 +114,7 @@ class ExceptionListener
}
} else {
if (null !== $this->logger) {
- $this->logger->debug('Access is denied (and user is neither anonymous, nor remember-me)');
+ $this->logger->debug(sprintf('Access is denied (and user is neither anonymous, nor remember-me) by "%s" at line %s', $exception->getFile(), $exception->getLine()));
}
try {
@@ -125,10 +129,7 @@ class ExceptionListener
$subRequest->attributes->set(SecurityContextInterface::ACCESS_DENIED_ERROR, $exception);
$response = $event->getKernel()->handle($subRequest, HttpKernelInterface::SUB_REQUEST, true);
- $response->setStatusCode(403);
} else {
- $event->setException(new AccessDeniedHttpException($exception->getMessage(), $exception));
-
return;
}
} catch (\Exception $e) {
@@ -141,6 +142,12 @@ class ExceptionListener
return;
}
}
+ } elseif ($exception instanceof LogoutException) {
+ if (null !== $this->logger) {
+ $this->logger->info(sprintf('Logout exception occurred; wrapping with AccessDeniedHttpException (%s)', $exception->getMessage()));
+ }
+
+ return;
} else {
return;
}
@@ -160,10 +167,9 @@ class ExceptionListener
$this->setTargetPath($request);
- if ($authException instanceof AccountStatusException && ($token = $this->context->getToken()) instanceof UsernamePasswordToken) {
+ if ($authException instanceof AccountStatusException) {
// remove the security token to prevent infinite redirect loops
$this->context->setToken(null);
- $request->getSession()->remove('_security_'.$token->getProviderKey());
}
return $this->authenticationEntryPoint->start($request, $authException);
@@ -173,7 +179,7 @@ class ExceptionListener
{
// session isn't required when using http basic authentication mechanism for example
if ($request->hasSession() && $request->isMethodSafe()) {
- $request->getSession()->set('_security.target_path', $request->getUri());
+ $request->getSession()->set('_security.' . $this->providerKey . '.target_path', $request->getUri());
}
}
}
diff --git a/Http/Firewall/LogoutListener.php b/Http/Firewall/LogoutListener.php
index 07244f5..32a0511 100644
--- a/Http/Firewall/LogoutListener.php
+++ b/Http/Firewall/LogoutListener.php
@@ -11,13 +11,15 @@
namespace Symfony\Component\Security\Http\Firewall;
-use Symfony\Component\Security\Http\Logout\LogoutSuccessHandlerInterface;
-
-use Symfony\Component\Security\Http\Logout\LogoutHandlerInterface;
-use Symfony\Component\Security\Core\SecurityContextInterface;
-use Symfony\Component\Security\Http\HttpUtils;
+use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface;
+use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
+use Symfony\Component\Security\Core\SecurityContextInterface;
+use Symfony\Component\Security\Core\Exception\LogoutException;
+use Symfony\Component\Security\Http\HttpUtils;
+use Symfony\Component\Security\Http\Logout\LogoutHandlerInterface;
+use Symfony\Component\Security\Http\Logout\LogoutSuccessHandlerInterface;
/**
* LogoutListener logout users.
@@ -27,28 +29,32 @@ use Symfony\Component\HttpKernel\Event\GetResponseEvent;
class LogoutListener implements ListenerInterface
{
private $securityContext;
- private $logoutPath;
- private $targetUrl;
+ private $options;
private $handlers;
private $successHandler;
private $httpUtils;
+ private $csrfProvider;
/**
* Constructor
*
* @param SecurityContextInterface $securityContext
* @param HttpUtils $httpUtils An HttpUtilsInterface instance
- * @param string $logoutPath The path that starts the logout process
- * @param string $targetUrl The URL to redirect to after logout
- * @param LogoutSuccessHandlerInterface $successHandler
+ * @param LogoutSuccessHandlerInterface $successHandler A LogoutSuccessHandlerInterface instance
+ * @param array $options An array of options to process a logout attempt
+ * @param CsrfProviderInterface $csrfProvider A CsrfProviderInterface instance
*/
- public function __construct(SecurityContextInterface $securityContext, HttpUtils $httpUtils, $logoutPath, $targetUrl = '/', LogoutSuccessHandlerInterface $successHandler = null)
+ public function __construct(SecurityContextInterface $securityContext, HttpUtils $httpUtils, LogoutSuccessHandlerInterface $successHandler, array $options = array(), CsrfProviderInterface $csrfProvider = null)
{
$this->securityContext = $securityContext;
$this->httpUtils = $httpUtils;
- $this->logoutPath = $logoutPath;
- $this->targetUrl = $targetUrl;
+ $this->options = array_merge(array(
+ 'csrf_parameter' => '_csrf_token',
+ 'intention' => 'logout',
+ 'logout_path' => '/logout',
+ ), $options);
$this->successHandler = $successHandler;
+ $this->csrfProvider = $csrfProvider;
$this->handlers = array();
}
@@ -56,8 +62,6 @@ class LogoutListener implements ListenerInterface
* Adds a logout handler
*
* @param LogoutHandlerInterface $handler
- *
- * @return void
*/
public function addHandler(LogoutHandlerInterface $handler)
{
@@ -67,24 +71,32 @@ class LogoutListener implements ListenerInterface
/**
* Performs the logout if requested
*
+ * If a CsrfProviderInterface instance is available, it will be used to
+ * validate the request.
+ *
* @param GetResponseEvent $event A GetResponseEvent instance
+ * @throws InvalidCsrfTokenException if the CSRF token is invalid
+ * @throws RuntimeException if the LogoutSuccessHandlerInterface instance does not return a response
*/
public function handle(GetResponseEvent $event)
{
$request = $event->getRequest();
- if (!$this->httpUtils->checkRequestPath($request, $this->logoutPath)) {
+ if (!$this->requiresLogout($request)) {
return;
}
- if (null !== $this->successHandler) {
- $response = $this->successHandler->onLogoutSuccess($request);
+ if (null !== $this->csrfProvider) {
+ $csrfToken = $request->get($this->options['csrf_parameter'], null, true);
- if (!$response instanceof Response) {
- throw new \RuntimeException('Logout Success Handler did not return a Response.');
+ if (false === $this->csrfProvider->isCsrfTokenValid($this->options['intention'], $csrfToken)) {
+ throw new LogoutException('Invalid CSRF token.');
}
- } else {
- $response = $this->httpUtils->createRedirectResponse($request, $this->targetUrl);
+ }
+
+ $response = $this->successHandler->onLogoutSuccess($request);
+ if (!$response instanceof Response) {
+ throw new \RuntimeException('Logout Success Handler did not return a Response.');
}
// handle multiple logout attempts gracefully
@@ -98,4 +110,20 @@ class LogoutListener implements ListenerInterface
$event->setResponse($response);
}
+
+ /**
+ * Whether this request is asking for logout.
+ *
+ * The default implementation only processed requests to a specific path,
+ * but a subclass could change this to logout requests where
+ * certain parameters is present.
+ *
+ * @param Request $request
+ *
+ * @return Boolean
+ */
+ protected function requiresLogout(Request $request)
+ {
+ return $this->httpUtils->checkRequestPath($request, $this->options['logout_path']);
+ }
}
diff --git a/Http/Firewall/RememberMeListener.php b/Http/Firewall/RememberMeListener.php
index ccda113..3614f79 100644
--- a/Http/Firewall/RememberMeListener.php
+++ b/Http/Firewall/RememberMeListener.php
@@ -1,5 +1,14 @@
<?php
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
namespace Symfony\Component\Security\Http\Firewall;
use Symfony\Component\HttpKernel\Log\LoggerInterface;
@@ -12,15 +21,6 @@ use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
use Symfony\Component\Security\Http\SecurityEvents;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
-/*
- * This file is part of the Symfony framework.
- *
- * (c) Fabien Potencier <fabien@symfony.com>
- *
- * This source file is subject to the MIT license that is bundled
- * with this source code in the file LICENSE.
- */
-
/**
* RememberMeListener implements authentication capabilities via a cookie
*
diff --git a/Http/Firewall/SwitchUserListener.php b/Http/Firewall/SwitchUserListener.php
index 9780860..7f0aa78 100644
--- a/Http/Firewall/SwitchUserListener.php
+++ b/Http/Firewall/SwitchUserListener.php
@@ -86,9 +86,7 @@ class SwitchUserListener implements ListenerInterface
try {
$this->securityContext->setToken($this->attemptSwitchUser($request));
} catch (AuthenticationException $e) {
- if (null !== $this->logger) {
- $this->logger->warn(sprintf('Switch User failed: "%s"', $e->getMessage()));
- }
+ throw new \LogicException(sprintf('Switch User failed: "%s"', $e->getMessage()));
}
}
@@ -108,8 +106,14 @@ class SwitchUserListener implements ListenerInterface
private function attemptSwitchUser(Request $request)
{
$token = $this->securityContext->getToken();
- if (false !== $this->getOriginalToken($token)) {
- throw new \LogicException(sprintf('You are already switched to "%s" user.', $token->getUsername()));
+ $originalToken = $this->getOriginalToken($token);
+
+ if (false !== $originalToken) {
+ if ($token->getUsername() === $request->get($this->usernameParameter)) {
+ return $token;
+ } else {
+ throw new \LogicException(sprintf('You are already switched to "%s" user.', $token->getUsername()));
+ }
}
if (false === $this->accessDecisionManager->decide($token, array($this->role))) {
@@ -148,7 +152,7 @@ class SwitchUserListener implements ListenerInterface
private function attemptExitUser(Request $request)
{
if (false === $original = $this->getOriginalToken($this->securityContext->getToken())) {
- throw new AuthenticationCredentialsNotFoundException(sprintf('Could not find original Token object.'));
+ throw new AuthenticationCredentialsNotFoundException('Could not find original Token object.');
}
if (null !== $this->dispatcher) {
diff --git a/Http/Firewall/UsernamePasswordFormAuthenticationListener.php b/Http/Firewall/UsernamePasswordFormAuthenticationListener.php
index bd2cec1..22330a8 100644
--- a/Http/Firewall/UsernamePasswordFormAuthenticationListener.php
+++ b/Http/Firewall/UsernamePasswordFormAuthenticationListener.php
@@ -37,15 +37,15 @@ class UsernamePasswordFormAuthenticationListener extends AbstractAuthenticationL
/**
* {@inheritdoc}
*/
- public function __construct(SecurityContextInterface $securityContext, AuthenticationManagerInterface $authenticationManager, SessionAuthenticationStrategyInterface $sessionStrategy, HttpUtils $httpUtils, $providerKey, array $options = array(), AuthenticationSuccessHandlerInterface $successHandler = null, AuthenticationFailureHandlerInterface $failureHandler = null, LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null, CsrfProviderInterface $csrfProvider = null)
+ public function __construct(SecurityContextInterface $securityContext, AuthenticationManagerInterface $authenticationManager, SessionAuthenticationStrategyInterface $sessionStrategy, HttpUtils $httpUtils, $providerKey, AuthenticationSuccessHandlerInterface $successHandler, AuthenticationFailureHandlerInterface $failureHandler, array $options = array(), LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null, CsrfProviderInterface $csrfProvider = null)
{
- parent::__construct($securityContext, $authenticationManager, $sessionStrategy, $httpUtils, $providerKey, array_merge(array(
+ parent::__construct($securityContext, $authenticationManager, $sessionStrategy, $httpUtils, $providerKey, $successHandler, $failureHandler, array_merge(array(
'username_parameter' => '_username',
'password_parameter' => '_password',
'csrf_parameter' => '_csrf_token',
'intention' => 'authenticate',
'post_only' => true,
- ), $options), $successHandler, $failureHandler, $logger, $dispatcher);
+ ), $options), $logger, $dispatcher);
$this->csrfProvider = $csrfProvider;
}
@@ -53,6 +53,18 @@ class UsernamePasswordFormAuthenticationListener extends AbstractAuthenticationL
/**
* {@inheritdoc}
*/
+ protected function requiresAuthentication(Request $request)
+ {
+ if ($this->options['post_only'] && !$request->isMethod('post')) {
+ return false;
+ }
+
+ return parent::requiresAuthentication($request);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
protected function attemptAuthentication(Request $request)
{
if ($this->options['post_only'] && 'post' !== strtolower($request->getMethod())) {