Upgrade 1-11.38

This commit is contained in:
xesmyd
2026-03-30 14:10:30 +02:00
parent f2a7e6d1fc
commit ac648ef29d
24665 changed files with 69682 additions and 2205004 deletions
@@ -11,25 +11,25 @@
namespace Symfony\Component\Security\Http\Firewall;
use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface;
use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface;
use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface;
use Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface;
use Symfony\Component\Security\Core\Security;
use Psr\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Exception\SessionUnavailableException;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface;
use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
use Symfony\Component\Security\Http\SecurityEvents;
use Symfony\Component\Security\Http\HttpUtils;
use Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface;
use Symfony\Component\Security\Http\SecurityEvents;
use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface;
/**
* The AbstractAuthenticationListener is the preferred base class for all
@@ -64,23 +64,18 @@ abstract class AbstractAuthenticationListener implements ListenerInterface
private $rememberMeServices;
/**
* Constructor.
*
* @param TokenStorageInterface $tokenStorage A TokenStorageInterface instance
* @param AuthenticationManagerInterface $authenticationManager An AuthenticationManagerInterface instance
* @param SessionAuthenticationStrategyInterface $sessionStrategy
* @param HttpUtils $httpUtils An HttpUtils 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 LoggerInterface|null $logger A LoggerInterface instance
* @param EventDispatcherInterface|null $dispatcher An EventDispatcherInterface instance
* @param TokenStorageInterface $tokenStorage A TokenStorageInterface instance
* @param AuthenticationManagerInterface $authenticationManager An AuthenticationManagerInterface instance
* @param HttpUtils $httpUtils An HttpUtils instance
* @param string $providerKey
* @param array $options An array of options for the processing of a
* successful, or failed authentication attempt
* @param LoggerInterface|null $logger A LoggerInterface instance
* @param EventDispatcherInterface|null $dispatcher An EventDispatcherInterface instance
*
* @throws \InvalidArgumentException
*/
public function __construct(TokenStorageInterface $tokenStorage, AuthenticationManagerInterface $authenticationManager, SessionAuthenticationStrategyInterface $sessionStrategy, HttpUtils $httpUtils, $providerKey, AuthenticationSuccessHandlerInterface $successHandler, AuthenticationFailureHandlerInterface $failureHandler, array $options = array(), LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null)
public function __construct(TokenStorageInterface $tokenStorage, AuthenticationManagerInterface $authenticationManager, SessionAuthenticationStrategyInterface $sessionStrategy, HttpUtils $httpUtils, $providerKey, AuthenticationSuccessHandlerInterface $successHandler, AuthenticationFailureHandlerInterface $failureHandler, array $options = [], LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null)
{
if (empty($providerKey)) {
throw new \InvalidArgumentException('$providerKey must not be empty.');
@@ -92,7 +87,7 @@ abstract class AbstractAuthenticationListener implements ListenerInterface
$this->providerKey = $providerKey;
$this->successHandler = $successHandler;
$this->failureHandler = $failureHandler;
$this->options = array_merge(array(
$this->options = array_merge([
'check_path' => '/login_check',
'login_path' => '/login',
'always_use_default_target_path' => false,
@@ -102,7 +97,7 @@ abstract class AbstractAuthenticationListener implements ListenerInterface
'failure_path' => null,
'failure_forward' => false,
'require_previous_session' => true,
), $options);
], $options);
$this->logger = $logger;
$this->dispatcher = $dispatcher;
$this->httpUtils = $httpUtils;
@@ -110,8 +105,6 @@ abstract class AbstractAuthenticationListener implements ListenerInterface
/**
* Sets the RememberMeServices implementation to use.
*
* @param RememberMeServicesInterface $rememberMeServices
*/
public function setRememberMeServices(RememberMeServicesInterface $rememberMeServices)
{
@@ -121,8 +114,6 @@ abstract class AbstractAuthenticationListener implements ListenerInterface
/**
* Handles form based authentication.
*
* @param GetResponseEvent $event A GetResponseEvent instance
*
* @throws \RuntimeException
* @throws SessionUnavailableException
*/
@@ -170,8 +161,6 @@ abstract class AbstractAuthenticationListener implements ListenerInterface
* but a subclass could change this to only authenticate requests where a
* certain parameters is present.
*
* @param Request $request
*
* @return bool
*/
protected function requiresAuthentication(Request $request)
@@ -182,8 +171,6 @@ abstract class AbstractAuthenticationListener implements ListenerInterface
/**
* Performs authentication.
*
* @param Request $request A Request instance
*
* @return TokenInterface|Response|null The authenticated token, null if full authentication is not possible, or a Response
*
* @throws AuthenticationException if the authentication fails
@@ -193,7 +180,7 @@ abstract class AbstractAuthenticationListener implements ListenerInterface
private function onFailure(Request $request, AuthenticationException $failed)
{
if (null !== $this->logger) {
$this->logger->info('Authentication request failed.', array('exception' => $failed));
$this->logger->info('Authentication request failed.', ['exception' => $failed]);
}
$token = $this->tokenStorage->getToken();
@@ -213,7 +200,7 @@ abstract class AbstractAuthenticationListener implements ListenerInterface
private function onSuccess(Request $request, TokenInterface $token)
{
if (null !== $this->logger) {
$this->logger->info('User has been authenticated successfully.', array('username' => $token->getUsername()));
$this->logger->info('User has been authenticated successfully.', ['username' => $token->getUsername()]);
}
$this->tokenStorage->setToken($token);
@@ -11,17 +11,19 @@
namespace Symfony\Component\Security\Http\Firewall;
use Psr\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
use Symfony\Component\Security\Core\Authentication\Token\PreAuthenticatedToken;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
use Symfony\Component\Security\Http\SecurityEvents;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface;
/**
* AbstractPreAuthenticatedListener is the base class for all listener that
@@ -37,6 +39,7 @@ abstract class AbstractPreAuthenticatedListener implements ListenerInterface
private $authenticationManager;
private $providerKey;
private $dispatcher;
private $sessionStrategy;
public function __construct(TokenStorageInterface $tokenStorage, AuthenticationManagerInterface $authenticationManager, $providerKey, LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null)
{
@@ -49,8 +52,6 @@ abstract class AbstractPreAuthenticatedListener implements ListenerInterface
/**
* Handles pre-authentication.
*
* @param GetResponseEvent $event A GetResponseEvent instance
*/
final public function handle(GetResponseEvent $event)
{
@@ -65,7 +66,7 @@ abstract class AbstractPreAuthenticatedListener implements ListenerInterface
}
if (null !== $this->logger) {
$this->logger->debug('Checking current security token.', array('token' => (string) $this->tokenStorage->getToken()));
$this->logger->debug('Checking current security token.', ['token' => (string) $this->tokenStorage->getToken()]);
}
if (null !== $token = $this->tokenStorage->getToken()) {
@@ -75,15 +76,18 @@ abstract class AbstractPreAuthenticatedListener implements ListenerInterface
}
if (null !== $this->logger) {
$this->logger->debug('Trying to pre-authenticate user.', array('username' => (string) $user));
$this->logger->debug('Trying to pre-authenticate user.', ['username' => (string) $user]);
}
try {
$token = $this->authenticationManager->authenticate(new PreAuthenticatedToken($user, $credentials, $this->providerKey));
if (null !== $this->logger) {
$this->logger->info('Pre-authentication successful.', array('token' => (string) $token));
$this->logger->info('Pre-authentication successful.', ['token' => (string) $token]);
}
$this->migrateSession($request, $token);
$this->tokenStorage->setToken($token);
if (null !== $this->dispatcher) {
@@ -96,9 +100,17 @@ abstract class AbstractPreAuthenticatedListener implements ListenerInterface
}
/**
* Clears a PreAuthenticatedToken for this provider (if present).
* Call this method if your authentication token is stored to a session.
*
* @param AuthenticationException $exception
* @final
*/
public function setSessionAuthenticationStrategy(SessionAuthenticationStrategyInterface $sessionStrategy)
{
$this->sessionStrategy = $sessionStrategy;
}
/**
* Clears a PreAuthenticatedToken for this provider (if present).
*/
private function clearToken(AuthenticationException $exception)
{
@@ -107,7 +119,7 @@ abstract class AbstractPreAuthenticatedListener implements ListenerInterface
$this->tokenStorage->setToken(null);
if (null !== $this->logger) {
$this->logger->info('Cleared security token due to an exception.', array('exception' => $exception));
$this->logger->info('Cleared security token due to an exception.', ['exception' => $exception]);
}
}
}
@@ -115,9 +127,16 @@ abstract class AbstractPreAuthenticatedListener implements ListenerInterface
/**
* Gets the user and credentials from the Request.
*
* @param Request $request A Request instance
*
* @return array An array composed of the user and the credentials
*/
abstract protected function getPreAuthenticatedData(Request $request);
private function migrateSession(Request $request, TokenInterface $token)
{
if (!$this->sessionStrategy || !$request->hasSession() || !$request->hasPreviousSession()) {
return;
}
$this->sessionStrategy->onAuthentication($request, $token);
}
}
+4 -6
View File
@@ -11,13 +11,13 @@
namespace Symfony\Component\Security\Http\Firewall;
use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;
use Symfony\Component\Security\Http\AccessMapInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException;
use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException;
use Symfony\Component\Security\Http\AccessMapInterface;
/**
* AccessListener enforces access control rules.
@@ -42,8 +42,6 @@ class AccessListener implements ListenerInterface
/**
* Handles access authorization.
*
* @param GetResponseEvent $event A GetResponseEvent instance
*
* @throws AccessDeniedException
* @throws AuthenticationCredentialsNotFoundException
*/
@@ -11,12 +11,12 @@
namespace Symfony\Component\Security\Http\Firewall;
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
/**
* AnonymousAuthenticationListener automatically adds a Token if none is
@@ -41,8 +41,6 @@ class AnonymousAuthenticationListener implements ListenerInterface
/**
* Handles anonymous authentication.
*
* @param GetResponseEvent $event A GetResponseEvent instance
*/
public function handle(GetResponseEvent $event)
{
@@ -51,7 +49,7 @@ class AnonymousAuthenticationListener implements ListenerInterface
}
try {
$token = new AnonymousToken($this->secret, 'anon.', array());
$token = new AnonymousToken($this->secret, 'anon.', []);
if (null !== $this->authenticationManager) {
$token = $this->authenticationManager->authenticate($token);
}
@@ -63,7 +61,7 @@ class AnonymousAuthenticationListener implements ListenerInterface
}
} catch (AuthenticationException $failed) {
if (null !== $this->logger) {
$this->logger->info('Anonymous authentication failed.', array('exception' => $failed));
$this->logger->info('Anonymous authentication failed.', ['exception' => $failed]);
}
}
}
@@ -11,13 +11,16 @@
namespace Symfony\Component\Security\Http\Firewall;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface;
use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface;
/**
* BasicAuthenticationListener implements Basic HTTP authentication.
@@ -32,6 +35,7 @@ class BasicAuthenticationListener implements ListenerInterface
private $authenticationEntryPoint;
private $logger;
private $ignoreFailure;
private $sessionStrategy;
public function __construct(TokenStorageInterface $tokenStorage, AuthenticationManagerInterface $authenticationManager, $providerKey, AuthenticationEntryPointInterface $authenticationEntryPoint, LoggerInterface $logger = null)
{
@@ -49,8 +53,6 @@ class BasicAuthenticationListener implements ListenerInterface
/**
* Handles basic authentication.
*
* @param GetResponseEvent $event A GetResponseEvent instance
*/
public function handle(GetResponseEvent $event)
{
@@ -67,11 +69,14 @@ class BasicAuthenticationListener implements ListenerInterface
}
if (null !== $this->logger) {
$this->logger->info('Basic authentication Authorization header found for user.', array('username' => $username));
$this->logger->info('Basic authentication Authorization header found for user.', ['username' => $username]);
}
try {
$token = $this->authenticationManager->authenticate(new UsernamePasswordToken($username, $request->headers->get('PHP_AUTH_PW'), $this->providerKey));
$this->migrateSession($request, $token);
$this->tokenStorage->setToken($token);
} catch (AuthenticationException $e) {
$token = $this->tokenStorage->getToken();
@@ -80,7 +85,7 @@ class BasicAuthenticationListener implements ListenerInterface
}
if (null !== $this->logger) {
$this->logger->info('Basic authentication failed for user.', array('username' => $username, 'exception' => $e));
$this->logger->info('Basic authentication failed for user.', ['username' => $username, 'exception' => $e]);
}
if ($this->ignoreFailure) {
@@ -90,4 +95,23 @@ class BasicAuthenticationListener implements ListenerInterface
$event->setResponse($this->authenticationEntryPoint->start($request, $e));
}
}
/**
* Call this method if your authentication token is stored to a session.
*
* @final
*/
public function setSessionAuthenticationStrategy(SessionAuthenticationStrategyInterface $sessionStrategy)
{
$this->sessionStrategy = $sessionStrategy;
}
private function migrateSession(Request $request, TokenInterface $token)
{
if (!$this->sessionStrategy || !$request->hasSession() || !$request->hasPreviousSession()) {
return;
}
$this->sessionStrategy->onAuthentication($request, $token);
}
}
+2 -4
View File
@@ -11,10 +11,10 @@
namespace Symfony\Component\Security\Http\Firewall;
use Symfony\Component\Security\Http\AccessMapInterface;
use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\Security\Http\AccessMapInterface;
use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface;
/**
* ChannelListener switches the HTTP protocol based on the access control
@@ -37,8 +37,6 @@ class ChannelListener implements ListenerInterface
/**
* Handles channel management.
*
* @param GetResponseEvent $event A GetResponseEvent instance
*/
public function handle(GetResponseEvent $event)
{
+132 -32
View File
@@ -12,8 +12,9 @@
namespace Symfony\Component\Security\Http\Firewall;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolver;
use Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolverInterface;
@@ -21,11 +22,12 @@ use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken;
use Symfony\Component\Security\Core\Authentication\Token\RememberMeToken;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\Role\SwitchUserRole;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface;
/**
* ContextListener manages the SecurityContext persistence through a session.
@@ -36,29 +38,27 @@ use Symfony\Component\EventDispatcher\EventDispatcherInterface;
class ContextListener implements ListenerInterface
{
private $tokenStorage;
private $contextKey;
private $sessionKey;
private $logger;
private $userProviders;
private $dispatcher;
private $registered;
private $trustResolver;
private $logoutOnUserChange = false;
private $rememberMeServices;
public function __construct(TokenStorageInterface $tokenStorage, array $userProviders, $contextKey, LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null, AuthenticationTrustResolverInterface $trustResolver = null)
/**
* @param iterable|UserProviderInterface[] $userProviders
* @param string $contextKey
*/
public function __construct(TokenStorageInterface $tokenStorage, $userProviders, $contextKey, LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null, AuthenticationTrustResolverInterface $trustResolver = null)
{
if (empty($contextKey)) {
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->tokenStorage = $tokenStorage;
$this->userProviders = $userProviders;
$this->contextKey = $contextKey;
$this->sessionKey = '_security_'.$contextKey;
$this->logger = $logger;
$this->dispatcher = $dispatcher;
@@ -66,14 +66,22 @@ class ContextListener implements ListenerInterface
}
/**
* Reads the Security Token from the session.
* Enables deauthentication during refreshUser when the user has changed.
*
* @param GetResponseEvent $event A GetResponseEvent instance
* @param bool $logoutOnUserChange
*/
public function setLogoutOnUserChange($logoutOnUserChange)
{
$this->logoutOnUserChange = (bool) $logoutOnUserChange;
}
/**
* Reads the Security Token from the session.
*/
public function handle(GetResponseEvent $event)
{
if (!$this->registered && null !== $this->dispatcher && $event->isMasterRequest()) {
$this->dispatcher->addListener(KernelEvents::RESPONSE, array($this, 'onKernelResponse'));
$this->dispatcher->addListener(KernelEvents::RESPONSE, [$this, 'onKernelResponse']);
$this->registered = true;
}
@@ -86,17 +94,24 @@ class ContextListener implements ListenerInterface
return;
}
$token = unserialize($token);
$token = $this->safelyUnserialize($token);
if (null !== $this->logger) {
$this->logger->debug('Read existing security token from the session.', array('key' => $this->sessionKey));
$this->logger->debug('Read existing security token from the session.', [
'key' => $this->sessionKey,
'token_class' => \is_object($token) ? \get_class($token) : null,
]);
}
if ($token instanceof TokenInterface) {
$token = $this->refreshUser($token);
if (!$token && $this->logoutOnUserChange && $this->rememberMeServices) {
$this->rememberMeServices->loginFail($request);
}
} elseif (null !== $token) {
if (null !== $this->logger) {
$this->logger->warning('Expected a security token from the session, got something else.', array('key' => $this->sessionKey, 'received' => $token));
$this->logger->warning('Expected a security token from the session, got something else.', ['key' => $this->sessionKey, 'received' => $token]);
}
$token = null;
@@ -107,8 +122,6 @@ class ContextListener implements ListenerInterface
/**
* Writes the security token into the session.
*
* @param FilterResponseEvent $event A FilterResponseEvent instance
*/
public function onKernelResponse(FilterResponseEvent $event)
{
@@ -116,14 +129,14 @@ class ContextListener implements ListenerInterface
return;
}
if (!$event->getRequest()->hasSession()) {
$request = $event->getRequest();
if (!$request->hasSession()) {
return;
}
$this->dispatcher->removeListener(KernelEvents::RESPONSE, array($this, 'onKernelResponse'));
$this->dispatcher->removeListener(KernelEvents::RESPONSE, [$this, 'onKernelResponse']);
$this->registered = false;
$request = $event->getRequest();
$session = $request->getSession();
if ((null === $token = $this->tokenStorage->getToken()) || $this->trustResolver->isAnonymous($token)) {
@@ -134,7 +147,7 @@ class ContextListener implements ListenerInterface
$session->set($this->sessionKey, serialize($token));
if (null !== $this->logger) {
$this->logger->debug('Stored the security token in the session.', array('key' => $this->sessionKey));
$this->logger->debug('Stored the security token in the session.', ['key' => $this->sessionKey]);
}
}
}
@@ -142,8 +155,6 @@ class ContextListener implements ListenerInterface
/**
* Refreshes the user by reloading it from the user provider.
*
* @param TokenInterface $token
*
* @return TokenInterface|null
*
* @throws \RuntimeException
@@ -156,14 +167,51 @@ class ContextListener implements ListenerInterface
}
$userNotFoundByProvider = false;
$userDeauthenticated = false;
$userClass = \get_class($user);
foreach ($this->userProviders as $provider) {
if (!$provider instanceof UserProviderInterface) {
throw new \InvalidArgumentException(sprintf('User provider "%s" must implement "%s".', \get_class($provider), UserProviderInterface::class));
}
if (!$provider->supportsClass($userClass)) {
continue;
}
try {
$refreshedUser = $provider->refreshUser($user);
$newToken = clone $token;
$newToken->setUser($refreshedUser);
// tokens can be deauthenticated if the user has been changed.
if (!$newToken->isAuthenticated()) {
if ($this->logoutOnUserChange) {
$userDeauthenticated = true;
if (null !== $this->logger) {
$this->logger->debug('Cannot refresh token because user has changed.', ['username' => $refreshedUser->getUsername(), 'provider' => \get_class($provider)]);
}
continue;
}
@trigger_error('Refreshing a deauthenticated user is deprecated as of 3.4 and will trigger a logout in 4.0.', \E_USER_DEPRECATED);
}
$token->setUser($refreshedUser);
if (null !== $this->logger) {
$this->logger->debug('User was reloaded from a user provider.', array('username' => $refreshedUser->getUsername(), 'provider' => get_class($provider)));
$context = ['provider' => \get_class($provider), 'username' => $refreshedUser->getUsername()];
foreach ($token->getRoles() as $role) {
if ($role instanceof SwitchUserRole) {
$context['impersonator_username'] = $role->getSource()->getUsername();
break;
}
}
$this->logger->debug('User was reloaded from a user provider.', $context);
}
return $token;
@@ -171,17 +219,69 @@ class ContextListener implements ListenerInterface
// let's try the next user provider
} catch (UsernameNotFoundException $e) {
if (null !== $this->logger) {
$this->logger->warning('Username could not be found in the selected user provider.', array('username' => $e->getUsername(), 'provider' => get_class($provider)));
$this->logger->warning('Username could not be found in the selected user provider.', ['username' => $e->getUsername(), 'provider' => \get_class($provider)]);
}
$userNotFoundByProvider = true;
}
}
if ($userNotFoundByProvider) {
return;
if ($userDeauthenticated) {
if (null !== $this->logger) {
$this->logger->debug('Token was deauthenticated after trying to refresh it.');
}
return null;
}
throw new \RuntimeException(sprintf('There is no user provider for user "%s".', get_class($user)));
if ($userNotFoundByProvider) {
return null;
}
throw new \RuntimeException(sprintf('There is no user provider for user "%s". Shouldn\'t the "supportsClass()" method of your user provider return true for this classname?', $userClass));
}
private function safelyUnserialize($serializedToken)
{
$e = $token = null;
$prevUnserializeHandler = ini_set('unserialize_callback_func', __CLASS__.'::handleUnserializeCallback');
$prevErrorHandler = set_error_handler(function ($type, $msg, $file, $line, $context = []) use (&$prevErrorHandler) {
if (__FILE__ === $file) {
throw new \UnexpectedValueException($msg, 0x37313bc);
}
return $prevErrorHandler ? $prevErrorHandler($type, $msg, $file, $line, $context) : false;
});
try {
$token = unserialize($serializedToken);
} catch (\Error $e) {
} catch (\Exception $e) {
}
restore_error_handler();
ini_set('unserialize_callback_func', $prevUnserializeHandler);
if ($e) {
if (!$e instanceof \UnexpectedValueException || 0x37313bc !== $e->getCode()) {
throw $e;
}
if ($this->logger) {
$this->logger->warning('Failed to unserialize the security token from the session.', ['key' => $this->sessionKey, 'received' => $serializedToken, 'exception' => $e]);
}
}
return $token;
}
/**
* @internal
*/
public static function handleUnserializeCallback($class)
{
throw new \UnexpectedValueException('Class not found: '.$class, 0x37313bc);
}
public function setRememberMeServices(RememberMeServicesInterface $rememberMeServices)
{
$this->rememberMeServices = $rememberMeServices;
}
}
@@ -11,23 +11,27 @@
namespace Symfony\Component\Security\Http\Firewall;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Exception\AuthenticationServiceException;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
use Symfony\Component\Security\Core\Exception\NonceExpiredException;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Http\EntryPoint\DigestAuthenticationEntryPoint;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
use Symfony\Component\Security\Core\Exception\AuthenticationServiceException;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\Exception\NonceExpiredException;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface;
/**
* DigestAuthenticationListener implements Digest HTTP authentication.
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @deprecated since 3.4, to be removed in 4.0
*/
class DigestAuthenticationListener implements ListenerInterface
{
@@ -36,9 +40,12 @@ class DigestAuthenticationListener implements ListenerInterface
private $providerKey;
private $authenticationEntryPoint;
private $logger;
private $sessionStrategy;
public function __construct(TokenStorageInterface $tokenStorage, UserProviderInterface $provider, $providerKey, DigestAuthenticationEntryPoint $authenticationEntryPoint, LoggerInterface $logger = null)
{
@trigger_error(sprintf('The %s class and the whole HTTP digest authentication system is deprecated since Symfony 3.4 and will be removed in 4.0.', __CLASS__), \E_USER_DEPRECATED);
if (empty($providerKey)) {
throw new \InvalidArgumentException('$providerKey must not be empty.');
}
@@ -53,8 +60,6 @@ class DigestAuthenticationListener implements ListenerInterface
/**
* Handles digest authentication.
*
* @param GetResponseEvent $event A GetResponseEvent instance
*
* @throws AuthenticationServiceException
*/
public function handle(GetResponseEvent $event)
@@ -74,7 +79,7 @@ class DigestAuthenticationListener implements ListenerInterface
}
if (null !== $this->logger) {
$this->logger->debug('Digest Authorization header received from user agent.', array('header' => $header));
$this->logger->debug('Digest Authorization header received from user agent.', ['header' => $header]);
}
try {
@@ -89,7 +94,7 @@ class DigestAuthenticationListener implements ListenerInterface
$user = $this->provider->loadUserByUsername($digestAuth->getUsername());
if (null === $user) {
throw new AuthenticationServiceException('Digest User provider returned null, which is an interface contract violation');
throw new AuthenticationServiceException('Digest User provider returned null, which is an interface contract violation.');
}
$serverDigestMd5 = $digestAuth->calculateServerDigest($user->getPassword(), $request->getMethod());
@@ -101,7 +106,7 @@ class DigestAuthenticationListener implements ListenerInterface
if (!hash_equals($serverDigestMd5, $digestAuth->getResponse())) {
if (null !== $this->logger) {
$this->logger->debug('Unexpected response from the DigestAuth received; is the header returning a clear text passwords?', array('expected' => $serverDigestMd5, 'received' => $digestAuth->getResponse()));
$this->logger->debug('Unexpected response from the DigestAuth received; is the header returning a clear text passwords?', ['expected' => $serverDigestMd5, 'received' => $digestAuth->getResponse()]);
}
$this->fail($event, $request, new BadCredentialsException('Incorrect response'));
@@ -116,10 +121,23 @@ class DigestAuthenticationListener implements ListenerInterface
}
if (null !== $this->logger) {
$this->logger->info('Digest authentication successful.', array('username' => $digestAuth->getUsername(), 'received' => $digestAuth->getResponse()));
$this->logger->info('Digest authentication successful.', ['username' => $digestAuth->getUsername(), 'received' => $digestAuth->getResponse()]);
}
$this->tokenStorage->setToken(new UsernamePasswordToken($user, $user->getPassword(), $this->providerKey));
$token = new UsernamePasswordToken($user, $user->getPassword(), $this->providerKey);
$this->migrateSession($request, $token);
$this->tokenStorage->setToken($token);
}
/**
* Call this method if your authentication token is stored to a session.
*
* @final
*/
public function setSessionAuthenticationStrategy(SessionAuthenticationStrategyInterface $sessionStrategy)
{
$this->sessionStrategy = $sessionStrategy;
}
private function fail(GetResponseEvent $event, Request $request, AuthenticationException $authException)
@@ -130,23 +148,37 @@ class DigestAuthenticationListener implements ListenerInterface
}
if (null !== $this->logger) {
$this->logger->info('Digest authentication failed.', array('exception' => $authException));
$this->logger->info('Digest authentication failed.', ['exception' => $authException]);
}
$event->setResponse($this->authenticationEntryPoint->start($request, $authException));
}
private function migrateSession(Request $request, TokenInterface $token)
{
if (!$this->sessionStrategy || !$request->hasSession() || !$request->hasPreviousSession()) {
return;
}
$this->sessionStrategy->onAuthentication($request, $token);
}
}
/**
* @deprecated since 3.4, to be removed in 4.0.
*/
class DigestData
{
private $elements = array();
private $elements = [];
private $header;
private $nonceExpiryTime;
public function __construct($header)
{
@trigger_error(sprintf('The %s class and the whole HTTP digest authentication system is deprecated since Symfony 3.4 and will be removed in 4.0.', __CLASS__), \E_USER_DEPRECATED);
$this->header = $header;
preg_match_all('/(\w+)=("((?:[^"\\\\]|\\\\.)+)"|([^\s,$]+))/', $header, $matches, PREG_SET_ORDER);
preg_match_all('/(\w+)=("((?:[^"\\\\]|\\\\.)+)"|([^\s,$]+))/', $header, $matches, \PREG_SET_ORDER);
foreach ($matches as $match) {
if (isset($match[1]) && isset($match[3])) {
$this->elements[$match[1]] = isset($match[4]) ? $match[4] : $match[3];
@@ -161,17 +193,17 @@ class DigestData
public function getUsername()
{
return strtr($this->elements['username'], array('\\"' => '"', '\\\\' => '\\'));
return strtr($this->elements['username'], ['\\"' => '"', '\\\\' => '\\']);
}
public function validateAndDecode($entryPointKey, $expectedRealm)
{
if ($keys = array_diff(array('username', 'realm', 'nonce', 'uri', 'response'), array_keys($this->elements))) {
throw new BadCredentialsException(sprintf('Missing mandatory digest value; received header "%s" (%s)', $this->header, implode(', ', $keys)));
if ($keys = array_diff(['username', 'realm', 'nonce', 'uri', 'response'], array_keys($this->elements))) {
throw new BadCredentialsException(sprintf('Missing mandatory digest value; received header "%s" (%s).', $this->header, implode(', ', $keys)));
}
if ('auth' === $this->elements['qop'] && !isset($this->elements['nc'], $this->elements['cnonce'])) {
throw new BadCredentialsException(sprintf('Missing mandatory digest value; received header "%s"', $this->header));
throw new BadCredentialsException(sprintf('Missing mandatory digest value; received header "%s".', $this->header));
}
if ($expectedRealm !== $this->elements['realm']) {
@@ -184,7 +216,7 @@ class DigestData
$nonceTokens = explode(':', $nonceAsPlainText);
if (2 !== count($nonceTokens)) {
if (2 !== \count($nonceTokens)) {
throw new BadCredentialsException(sprintf('Nonce should have yielded two tokens but was "%s".', $nonceAsPlainText));
}
+49 -46
View File
@@ -11,26 +11,27 @@
namespace Symfony\Component\Security\Http\Firewall;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Http\Authorization\AccessDeniedHandlerInterface;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolverInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
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\Util\TargetPathTrait;
use Symfony\Component\Security\Http\HttpUtils;
use Symfony\Component\HttpFoundation\Request;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolverInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use Symfony\Component\Security\Core\Exception\AccountStatusException;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Exception\InsufficientAuthenticationException;
use Symfony\Component\Security\Core\Exception\LogoutException;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Security\Http\Authorization\AccessDeniedHandlerInterface;
use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface;
use Symfony\Component\Security\Http\HttpUtils;
use Symfony\Component\Security\Http\Util\TargetPathTrait;
/**
* ExceptionListener catches authentication exception and converts them to
@@ -67,39 +68,43 @@ class ExceptionListener
/**
* Registers a onKernelException listener to take care of security exceptions.
*
* @param EventDispatcherInterface $dispatcher An EventDispatcherInterface instance
*/
public function register(EventDispatcherInterface $dispatcher)
{
$dispatcher->addListener(KernelEvents::EXCEPTION, array($this, 'onKernelException'));
$dispatcher->addListener(KernelEvents::EXCEPTION, [$this, 'onKernelException'], 1);
}
/**
* Unregisters the dispatcher.
*
* @param EventDispatcherInterface $dispatcher An EventDispatcherInterface instance
*/
public function unregister(EventDispatcherInterface $dispatcher)
{
$dispatcher->removeListener(KernelEvents::EXCEPTION, array($this, 'onKernelException'));
$dispatcher->removeListener(KernelEvents::EXCEPTION, [$this, 'onKernelException']);
}
/**
* Handles security related exceptions.
*
* @param GetResponseForExceptionEvent $event An GetResponseForExceptionEvent instance
*/
public function onKernelException(GetResponseForExceptionEvent $event)
{
$exception = $event->getException();
do {
if ($exception instanceof AuthenticationException) {
return $this->handleAuthenticationException($event, $exception);
} elseif ($exception instanceof AccessDeniedException) {
return $this->handleAccessDeniedException($event, $exception);
} elseif ($exception instanceof LogoutException) {
return $this->handleLogoutException($exception);
$this->handleAuthenticationException($event, $exception);
return;
}
if ($exception instanceof AccessDeniedException) {
$this->handleAccessDeniedException($event, $exception);
return;
}
if ($exception instanceof LogoutException) {
$this->handleLogoutException($event, $exception);
return;
}
} while (null !== $exception = $exception->getPrevious());
}
@@ -107,11 +112,12 @@ class ExceptionListener
private function handleAuthenticationException(GetResponseForExceptionEvent $event, AuthenticationException $exception)
{
if (null !== $this->logger) {
$this->logger->info('An AuthenticationException was thrown; redirecting to authentication entry point.', array('exception' => $exception));
$this->logger->info('An AuthenticationException was thrown; redirecting to authentication entry point.', ['exception' => $exception]);
}
try {
$event->setResponse($this->startAuthentication($event->getRequest(), $exception));
$event->allowCustomResponseCode();
} catch (\Exception $e) {
$event->setException($e);
}
@@ -124,7 +130,7 @@ class ExceptionListener
$token = $this->tokenStorage->getToken();
if (!$this->authenticationTrustResolver->isFullFledged($token)) {
if (null !== $this->logger) {
$this->logger->debug('Access denied, the user is not fully authenticated; redirecting to authentication entry point.', array('exception' => $exception));
$this->logger->debug('Access denied, the user is not fully authenticated; redirecting to authentication entry point.', ['exception' => $exception]);
}
try {
@@ -140,7 +146,7 @@ class ExceptionListener
}
if (null !== $this->logger) {
$this->logger->debug('Access denied, the user is neither anonymous, nor remember-me.', array('exception' => $exception));
$this->logger->debug('Access denied, the user is neither anonymous, nor remember-me.', ['exception' => $exception]);
}
try {
@@ -155,27 +161,27 @@ class ExceptionListener
$subRequest->attributes->set(Security::ACCESS_DENIED_ERROR, $exception);
$event->setResponse($event->getKernel()->handle($subRequest, HttpKernelInterface::SUB_REQUEST, true));
$event->allowCustomResponseCode();
}
} catch (\Exception $e) {
if (null !== $this->logger) {
$this->logger->error('An exception was thrown when handling an AccessDeniedException.', array('exception' => $e));
$this->logger->error('An exception was thrown when handling an AccessDeniedException.', ['exception' => $e]);
}
$event->setException(new \RuntimeException('Exception thrown when handling an exception.', 0, $e));
}
}
private function handleLogoutException(LogoutException $exception)
private function handleLogoutException(GetResponseForExceptionEvent $event, LogoutException $exception)
{
$event->setException(new AccessDeniedHttpException($exception->getMessage(), $exception));
if (null !== $this->logger) {
$this->logger->info('A LogoutException was thrown.', array('exception' => $exception));
$this->logger->info('A LogoutException was thrown; wrapping with AccessDeniedHttpException', ['exception' => $exception]);
}
}
/**
* @param Request $request
* @param AuthenticationException $authException
*
* @return Response
*
* @throws AuthenticationException
@@ -183,7 +189,7 @@ class ExceptionListener
private function startAuthentication(Request $request, AuthenticationException $authException)
{
if (null === $this->authenticationEntryPoint) {
throw $authException;
throw new HttpException(Response::HTTP_UNAUTHORIZED, $authException->getMessage(), $authException, [], $authException->getCode());
}
if (null !== $this->logger) {
@@ -199,24 +205,21 @@ class ExceptionListener
$this->tokenStorage->setToken(null);
if (null !== $this->logger) {
$this->logger->info('The security token was removed due to an AccountStatusException.', array('exception' => $authException));
$this->logger->info('The security token was removed due to an AccountStatusException.', ['exception' => $authException]);
}
}
$response = $this->authenticationEntryPoint->start($request, $authException);
if (!$response instanceof Response) {
$given = is_object($response) ? get_class($response) : gettype($response);
$given = \is_object($response) ? \get_class($response) : \gettype($response);
throw new \LogicException(sprintf('The %s::start() method must return a Response object (%s returned)', get_class($this->authenticationEntryPoint), $given));
throw new \LogicException(sprintf('The "%s::start()" method must return a Response object ("%s" returned).', \get_class($this->authenticationEntryPoint), $given));
}
return $response;
}
/**
* @param Request $request
*/
protected function setTargetPath(Request $request)
{
// session isn't required when using HTTP basic authentication mechanism for example
@@ -20,10 +20,5 @@ use Symfony\Component\HttpKernel\Event\GetResponseEvent;
*/
interface ListenerInterface
{
/**
* This interface must be implemented by firewall listeners.
*
* @param GetResponseEvent $event
*/
public function handle(GetResponseEvent $event);
}
+4 -16
View File
@@ -38,33 +38,25 @@ class LogoutListener implements ListenerInterface
private $csrfTokenManager;
/**
* Constructor.
*
* @param TokenStorageInterface $tokenStorage
* @param HttpUtils $httpUtils An HttpUtils instance
* @param LogoutSuccessHandlerInterface $successHandler A LogoutSuccessHandlerInterface instance
* @param array $options An array of options to process a logout attempt
* @param CsrfTokenManagerInterface|null $csrfTokenManager A CsrfTokenManagerInterface instance
*/
public function __construct(TokenStorageInterface $tokenStorage, HttpUtils $httpUtils, LogoutSuccessHandlerInterface $successHandler, array $options = array(), CsrfTokenManagerInterface $csrfTokenManager = null)
public function __construct(TokenStorageInterface $tokenStorage, HttpUtils $httpUtils, LogoutSuccessHandlerInterface $successHandler, array $options = [], CsrfTokenManagerInterface $csrfTokenManager = null)
{
$this->tokenStorage = $tokenStorage;
$this->httpUtils = $httpUtils;
$this->options = array_merge(array(
$this->options = array_merge([
'csrf_parameter' => '_csrf_token',
'csrf_token_id' => 'logout',
'logout_path' => '/logout',
), $options);
], $options);
$this->successHandler = $successHandler;
$this->csrfTokenManager = $csrfTokenManager;
$this->handlers = array();
$this->handlers = [];
}
/**
* Adds a logout handler.
*
* @param LogoutHandlerInterface $handler
*/
public function addHandler(LogoutHandlerInterface $handler)
{
$this->handlers[] = $handler;
@@ -76,8 +68,6 @@ class LogoutListener implements ListenerInterface
* If a CsrfTokenManagerInterface instance is available, it will be used to
* validate the request.
*
* @param GetResponseEvent $event A GetResponseEvent instance
*
* @throws LogoutException if the CSRF token is invalid
* @throws \RuntimeException if the LogoutSuccessHandlerInterface instance does not return a response
*/
@@ -121,8 +111,6 @@ class LogoutListener implements ListenerInterface
* but a subclass could change this to logout requests where
* certain parameters is present.
*
* @param Request $request
*
* @return bool
*/
protected function requiresLogout(Request $request)
+25 -17
View File
@@ -12,16 +12,16 @@
namespace Symfony\Component\Security\Http\Firewall;
use Psr\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
use Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface;
use Symfony\Component\Security\Http\SecurityEvents;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface;
use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategy;
use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface;
/**
* RememberMeListener implements authentication capabilities via a cookie.
@@ -39,15 +39,7 @@ class RememberMeListener implements ListenerInterface
private $sessionStrategy;
/**
* Constructor.
*
* @param TokenStorageInterface $tokenStorage
* @param RememberMeServicesInterface $rememberMeServices
* @param AuthenticationManagerInterface $authenticationManager
* @param LoggerInterface|null $logger
* @param EventDispatcherInterface|null $dispatcher
* @param bool $catchExceptions
* @param SessionAuthenticationStrategyInterface|null $sessionStrategy
* @param bool $catchExceptions
*/
public function __construct(TokenStorageInterface $tokenStorage, RememberMeServicesInterface $rememberMeServices, AuthenticationManagerInterface $authenticationManager, LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null, $catchExceptions = true, SessionAuthenticationStrategyInterface $sessionStrategy = null)
{
@@ -62,8 +54,6 @@ class RememberMeListener implements ListenerInterface
/**
* Handles remember-me cookie based authentication.
*
* @param GetResponseEvent $event A GetResponseEvent instance
*/
public function handle(GetResponseEvent $event)
{
@@ -72,7 +62,25 @@ class RememberMeListener implements ListenerInterface
}
$request = $event->getRequest();
if (null === $token = $this->rememberMeServices->autoLogin($request)) {
try {
if (null === $token = $this->rememberMeServices->autoLogin($request)) {
return;
}
} catch (AuthenticationException $e) {
if (null !== $this->logger) {
$this->logger->warning(
'The token storage was not populated with remember-me token as the'
.' RememberMeServices was not able to create a token from the remember'
.' me information.', ['exception' => $e]
);
}
$this->rememberMeServices->loginFail($request);
if (!$this->catchExceptions) {
throw $e;
}
return;
}
@@ -96,11 +104,11 @@ class RememberMeListener implements ListenerInterface
$this->logger->warning(
'The token storage was not populated with remember-me token as the'
.' AuthenticationManager rejected the AuthenticationToken returned'
.' by the RememberMeServices.', array('exception' => $e)
.' by the RememberMeServices.', ['exception' => $e]
);
}
$this->rememberMeServices->loginFail($request);
$this->rememberMeServices->loginFail($request, $e);
if (!$this->catchExceptions) {
throw $e;
@@ -11,12 +11,12 @@
namespace Symfony\Component\Security\Http\Firewall;
use Psr\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
/**
* REMOTE_USER authentication listener.
@@ -41,9 +41,9 @@ class RemoteUserAuthenticationListener extends AbstractPreAuthenticatedListener
protected function getPreAuthenticatedData(Request $request)
{
if (!$request->server->has($this->userKey)) {
throw new BadCredentialsException(sprintf('User key was not found: %s', $this->userKey));
throw new BadCredentialsException(sprintf('User key was not found: "%s".', $this->userKey));
}
return array($request->server->get($this->userKey), null);
return [$request->server->get($this->userKey), null];
}
}
@@ -11,22 +11,23 @@
namespace Symfony\Component\Security\Http\Firewall;
use Psr\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
use Symfony\Component\Security\Core\Exception\InvalidCsrfTokenException;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Security\Csrf\CsrfToken;
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface;
use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface;
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
use Symfony\Component\Security\Http\Authentication\SimpleFormAuthenticatorInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Security\Http\HttpUtils;
use Symfony\Component\Security\Http\ParameterBagUtils;
use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface;
use Psr\Log\LoggerInterface;
/**
* @author Jordi Boggiano <j.boggiano@seld.be>
@@ -37,40 +38,35 @@ class SimpleFormAuthenticationListener extends AbstractAuthenticationListener
private $csrfTokenManager;
/**
* Constructor.
*
* @param TokenStorageInterface $tokenStorage A TokenStorageInterface instance
* @param AuthenticationManagerInterface $authenticationManager An AuthenticationManagerInterface instance
* @param SessionAuthenticationStrategyInterface $sessionStrategy
* @param HttpUtils $httpUtils An HttpUtils 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 LoggerInterface|null $logger A LoggerInterface instance
* @param EventDispatcherInterface|null $dispatcher An EventDispatcherInterface instance
* @param CsrfTokenManagerInterface|null $csrfTokenManager A CsrfTokenManagerInterface instance
* @param SimpleFormAuthenticatorInterface|null $simpleAuthenticator A SimpleFormAuthenticatorInterface instance
* @param TokenStorageInterface $tokenStorage A TokenStorageInterface instance
* @param AuthenticationManagerInterface $authenticationManager An AuthenticationManagerInterface instance
* @param HttpUtils $httpUtils An HttpUtils instance
* @param string $providerKey
* @param array $options An array of options for the processing of a
* successful, or failed authentication attempt
* @param LoggerInterface|null $logger A LoggerInterface instance
* @param EventDispatcherInterface|null $dispatcher An EventDispatcherInterface instance
* @param CsrfTokenManagerInterface|null $csrfTokenManager A CsrfTokenManagerInterface instance
* @param SimpleFormAuthenticatorInterface|null $simpleAuthenticator A SimpleFormAuthenticatorInterface instance
*
* @throws \InvalidArgumentException In case no simple authenticator is provided
*/
public function __construct(TokenStorageInterface $tokenStorage, AuthenticationManagerInterface $authenticationManager, SessionAuthenticationStrategyInterface $sessionStrategy, HttpUtils $httpUtils, $providerKey, AuthenticationSuccessHandlerInterface $successHandler, AuthenticationFailureHandlerInterface $failureHandler, array $options = array(), LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null, CsrfTokenManagerInterface $csrfTokenManager = null, SimpleFormAuthenticatorInterface $simpleAuthenticator = null)
public function __construct(TokenStorageInterface $tokenStorage, AuthenticationManagerInterface $authenticationManager, SessionAuthenticationStrategyInterface $sessionStrategy, HttpUtils $httpUtils, $providerKey, AuthenticationSuccessHandlerInterface $successHandler, AuthenticationFailureHandlerInterface $failureHandler, array $options = [], LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null, CsrfTokenManagerInterface $csrfTokenManager = null, SimpleFormAuthenticatorInterface $simpleAuthenticator = null)
{
if (!$simpleAuthenticator) {
throw new \InvalidArgumentException('Missing simple authenticator');
throw new \InvalidArgumentException('Missing simple authenticator.');
}
$this->simpleAuthenticator = $simpleAuthenticator;
$this->csrfTokenManager = $csrfTokenManager;
$options = array_merge(array(
$options = array_merge([
'username_parameter' => '_username',
'password_parameter' => '_password',
'csrf_parameter' => '_csrf_token',
'csrf_token_id' => 'authenticate',
'post_only' => true,
), $options);
], $options);
parent::__construct($tokenStorage, $authenticationManager, $sessionStrategy, $httpUtils, $providerKey, $successHandler, $failureHandler, $options, $logger, $dispatcher);
}
@@ -101,14 +97,20 @@ class SimpleFormAuthenticationListener extends AbstractAuthenticationListener
}
if ($this->options['post_only']) {
$username = trim(ParameterBagUtils::getParameterBagValue($request->request, $this->options['username_parameter']));
$username = ParameterBagUtils::getParameterBagValue($request->request, $this->options['username_parameter']);
$password = ParameterBagUtils::getParameterBagValue($request->request, $this->options['password_parameter']);
} else {
$username = trim(ParameterBagUtils::getRequestParameterValue($request, $this->options['username_parameter']));
$username = ParameterBagUtils::getRequestParameterValue($request, $this->options['username_parameter']);
$password = ParameterBagUtils::getRequestParameterValue($request, $this->options['password_parameter']);
}
if (strlen($username) > Security::MAX_USERNAME_LENGTH) {
if (!\is_string($username) && (!\is_object($username) || !method_exists($username, '__toString'))) {
throw new BadRequestHttpException(sprintf('The key "%s" must be a string, "%s" given.', $this->options['username_parameter'], \gettype($username)));
}
$username = trim($username);
if (\strlen($username) > Security::MAX_USERNAME_LENGTH) {
throw new BadCredentialsException('Invalid username.');
}
@@ -11,19 +11,22 @@
namespace Symfony\Component\Security\Http\Firewall;
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Http\Authentication\SimplePreAuthenticatorInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface;
use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface;
use Symfony\Component\Security\Http\Authentication\SimplePreAuthenticatorInterface;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
use Symfony\Component\Security\Http\SecurityEvents;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface;
/**
* SimplePreAuthenticationListener implements simple proxying to an authenticator.
@@ -38,10 +41,9 @@ class SimplePreAuthenticationListener implements ListenerInterface
private $simpleAuthenticator;
private $logger;
private $dispatcher;
private $sessionStrategy;
/**
* Constructor.
*
* @param TokenStorageInterface $tokenStorage A TokenStorageInterface instance
* @param AuthenticationManagerInterface $authenticationManager An AuthenticationManagerInterface instance
* @param string $providerKey
@@ -64,16 +66,24 @@ class SimplePreAuthenticationListener implements ListenerInterface
}
/**
* Handles basic authentication.
* Call this method if your authentication token is stored to a session.
*
* @param GetResponseEvent $event A GetResponseEvent instance
* @final
*/
public function setSessionAuthenticationStrategy(SessionAuthenticationStrategyInterface $sessionStrategy)
{
$this->sessionStrategy = $sessionStrategy;
}
/**
* Handles basic authentication.
*/
public function handle(GetResponseEvent $event)
{
$request = $event->getRequest();
if (null !== $this->logger) {
$this->logger->info('Attempting SimplePreAuthentication.', array('key' => $this->providerKey, 'authenticator' => get_class($this->simpleAuthenticator)));
$this->logger->info('Attempting SimplePreAuthentication.', ['key' => $this->providerKey, 'authenticator' => \get_class($this->simpleAuthenticator)]);
}
if (null !== $this->tokenStorage->getToken() && !$this->tokenStorage->getToken() instanceof AnonymousToken) {
@@ -89,6 +99,9 @@ class SimplePreAuthenticationListener implements ListenerInterface
}
$token = $this->authenticationManager->authenticate($token);
$this->migrateSession($request, $token);
$this->tokenStorage->setToken($token);
if (null !== $this->dispatcher) {
@@ -99,7 +112,7 @@ class SimplePreAuthenticationListener implements ListenerInterface
$this->tokenStorage->setToken(null);
if (null !== $this->logger) {
$this->logger->info('SimplePreAuthentication request failed.', array('exception' => $e, 'authenticator' => get_class($this->simpleAuthenticator)));
$this->logger->info('SimplePreAuthentication request failed.', ['exception' => $e, 'authenticator' => \get_class($this->simpleAuthenticator)]);
}
if ($this->simpleAuthenticator instanceof AuthenticationFailureHandlerInterface) {
@@ -107,7 +120,7 @@ class SimplePreAuthenticationListener implements ListenerInterface
if ($response instanceof Response) {
$event->setResponse($response);
} elseif (null !== $response) {
throw new \UnexpectedValueException(sprintf('The %s::onAuthenticationFailure method must return null or a Response object', get_class($this->simpleAuthenticator)));
throw new \UnexpectedValueException(sprintf('The "%s::onAuthenticationFailure()" method must return null or a Response object.', \get_class($this->simpleAuthenticator)));
}
}
@@ -119,8 +132,17 @@ class SimplePreAuthenticationListener implements ListenerInterface
if ($response instanceof Response) {
$event->setResponse($response);
} elseif (null !== $response) {
throw new \UnexpectedValueException(sprintf('The %s::onAuthenticationSuccess method must return null or a Response object', get_class($this->simpleAuthenticator)));
throw new \UnexpectedValueException(sprintf('The "%s::onAuthenticationSuccess()" method must return null or a Response object.', \get_class($this->simpleAuthenticator)));
}
}
}
private function migrateSession(Request $request, TokenInterface $token)
{
if (!$this->sessionStrategy || !$request->hasSession() || !$request->hasPreviousSession()) {
return;
}
$this->sessionStrategy->onAuthentication($request, $token);
}
}
+53 -39
View File
@@ -11,24 +11,24 @@
namespace Symfony\Component\Security\Http\Firewall;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Core\User\UserCheckerInterface;
use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\Role\SwitchUserRole;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Role\SwitchUserRole;
use Symfony\Component\Security\Core\User\UserCheckerInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Http\Event\SwitchUserEvent;
use Symfony\Component\Security\Http\SecurityEvents;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
/**
* SwitchUserListener allows a user to impersonate another one temporarily
@@ -38,6 +38,8 @@ use Symfony\Component\EventDispatcher\EventDispatcherInterface;
*/
class SwitchUserListener implements ListenerInterface
{
const EXIT_VALUE = '_exit';
private $tokenStorage;
private $provider;
private $userChecker;
@@ -47,8 +49,9 @@ class SwitchUserListener implements ListenerInterface
private $role;
private $logger;
private $dispatcher;
private $stateless;
public function __construct(TokenStorageInterface $tokenStorage, UserProviderInterface $provider, UserCheckerInterface $userChecker, $providerKey, AccessDecisionManagerInterface $accessDecisionManager, LoggerInterface $logger = null, $usernameParameter = '_switch_user', $role = 'ROLE_ALLOWED_TO_SWITCH', EventDispatcherInterface $dispatcher = null)
public function __construct(TokenStorageInterface $tokenStorage, UserProviderInterface $provider, UserCheckerInterface $userChecker, $providerKey, AccessDecisionManagerInterface $accessDecisionManager, LoggerInterface $logger = null, $usernameParameter = '_switch_user', $role = 'ROLE_ALLOWED_TO_SWITCH', EventDispatcherInterface $dispatcher = null, $stateless = false)
{
if (empty($providerKey)) {
throw new \InvalidArgumentException('$providerKey must not be empty.');
@@ -63,88 +66,102 @@ class SwitchUserListener implements ListenerInterface
$this->role = $role;
$this->logger = $logger;
$this->dispatcher = $dispatcher;
$this->stateless = $stateless;
}
/**
* Handles the switch to another user.
*
* @param GetResponseEvent $event A GetResponseEvent instance
*
* @throws \LogicException if switching to a user failed
*/
public function handle(GetResponseEvent $event)
{
$request = $event->getRequest();
if (!$request->get($this->usernameParameter)) {
// usernames can be falsy
$username = $request->get($this->usernameParameter);
if (null === $username || '' === $username) {
$username = $request->headers->get($this->usernameParameter);
}
// if it's still "empty", nothing to do.
if (null === $username || '' === $username) {
return;
}
if ('_exit' === $request->get($this->usernameParameter)) {
if (null === $this->tokenStorage->getToken()) {
throw new AuthenticationCredentialsNotFoundException('Could not find original Token object.');
}
if (self::EXIT_VALUE === $username) {
$this->tokenStorage->setToken($this->attemptExitUser($request));
} else {
try {
$this->tokenStorage->setToken($this->attemptSwitchUser($request));
$this->tokenStorage->setToken($this->attemptSwitchUser($request, $username));
} catch (AuthenticationException $e) {
throw new \LogicException(sprintf('Switch User failed: "%s"', $e->getMessage()));
throw new \LogicException('Switch User failed: '.$e->getMessage());
}
}
$request->query->remove($this->usernameParameter);
$request->server->set('QUERY_STRING', http_build_query($request->query->all()));
if (!$this->stateless) {
$request->query->remove($this->usernameParameter);
$request->server->set('QUERY_STRING', http_build_query($request->query->all(), '', '&'));
$response = new RedirectResponse($request->getUri(), 302);
$response = new RedirectResponse($request->getUri(), 302);
$event->setResponse($response);
$event->setResponse($response);
}
}
/**
* Attempts to switch to another user.
*
* @param Request $request A Request instance
* @param Request $request A Request instance
* @param string $username
*
* @return TokenInterface|null The new TokenInterface if successfully switched, null otherwise
*
* @throws \LogicException
* @throws AccessDeniedException
*/
private function attemptSwitchUser(Request $request)
private function attemptSwitchUser(Request $request, $username)
{
$token = $this->tokenStorage->getToken();
$originalToken = $this->getOriginalToken($token);
if (false !== $originalToken) {
if ($token->getUsername() === $request->get($this->usernameParameter)) {
if ($token->getUsername() === $username) {
return $token;
}
throw new \LogicException(sprintf('You are already switched to "%s" user.', $token->getUsername()));
// User already switched, exit before seamlessly switching to another user
$token = $this->attemptExitUser($request);
}
if (false === $this->accessDecisionManager->decide($token, array($this->role))) {
if (false === $this->accessDecisionManager->decide($token, [$this->role])) {
$exception = new AccessDeniedException();
$exception->setAttributes($this->role);
throw $exception;
}
$username = $request->get($this->usernameParameter);
if (null !== $this->logger) {
$this->logger->info('Attempting to switch to user.', array('username' => $username));
$this->logger->info('Attempting to switch to user.', ['username' => $username]);
}
$user = $this->provider->loadUserByUsername($username);
$this->userChecker->checkPostAuth($user);
$roles = $user->getRoles();
$roles[] = new SwitchUserRole('ROLE_PREVIOUS_ADMIN', $this->tokenStorage->getToken());
$roles[] = new SwitchUserRole('ROLE_PREVIOUS_ADMIN', $token);
$token = new UsernamePasswordToken($user, $user->getPassword(), $this->providerKey, $roles);
if (null !== $this->dispatcher) {
$switchEvent = new SwitchUserEvent($request, $token->getUser());
$switchEvent = new SwitchUserEvent($request, $token->getUser(), $token);
$this->dispatcher->dispatch(SecurityEvents::SWITCH_USER, $switchEvent);
// use the token from the event in case any listeners have replaced it.
$token = $switchEvent->getToken();
}
return $token;
@@ -153,22 +170,21 @@ class SwitchUserListener implements ListenerInterface
/**
* Attempts to exit from an already switched user.
*
* @param Request $request A Request instance
*
* @return TokenInterface The original TokenInterface instance
*
* @throws AuthenticationCredentialsNotFoundException
*/
private function attemptExitUser(Request $request)
{
if (null === ($currentToken = $this->tokenStorage->getToken()) || false === $original = $this->getOriginalToken($currentToken)) {
if (false === $original = $this->getOriginalToken($this->tokenStorage->getToken())) {
throw new AuthenticationCredentialsNotFoundException('Could not find original Token object.');
}
if (null !== $this->dispatcher && $original->getUser() instanceof UserInterface) {
$user = $this->provider->refreshUser($original->getUser());
$switchEvent = new SwitchUserEvent($request, $user);
$switchEvent = new SwitchUserEvent($request, $user, $original);
$this->dispatcher->dispatch(SecurityEvents::SWITCH_USER, $switchEvent);
$original = $switchEvent->getToken();
}
return $original;
@@ -177,8 +193,6 @@ class SwitchUserListener implements ListenerInterface
/**
* Gets the original Token from a switched one.
*
* @param TokenInterface $token A switched TokenInterface instance
*
* @return TokenInterface|false The original TokenInterface instance, false if the current TokenInterface is not switched
*/
private function getOriginalToken(TokenInterface $token)
@@ -11,22 +11,23 @@
namespace Symfony\Component\Security\Http\Firewall;
use Symfony\Component\HttpFoundation\Request;
use Psr\Log\LoggerInterface;
use Symfony\Component\Security\Csrf\CsrfToken;
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface;
use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface;
use Symfony\Component\Security\Http\ParameterBagUtils;
use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface;
use Symfony\Component\Security\Http\HttpUtils;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
use Symfony\Component\Security\Core\Exception\InvalidCsrfTokenException;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Security\Csrf\CsrfToken;
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface;
use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface;
use Symfony\Component\Security\Http\HttpUtils;
use Symfony\Component\Security\Http\ParameterBagUtils;
use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface;
/**
* UsernamePasswordFormAuthenticationListener is the default implementation of
@@ -38,15 +39,15 @@ class UsernamePasswordFormAuthenticationListener extends AbstractAuthenticationL
{
private $csrfTokenManager;
public function __construct(TokenStorageInterface $tokenStorage, AuthenticationManagerInterface $authenticationManager, SessionAuthenticationStrategyInterface $sessionStrategy, HttpUtils $httpUtils, $providerKey, AuthenticationSuccessHandlerInterface $successHandler, AuthenticationFailureHandlerInterface $failureHandler, array $options = array(), LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null, CsrfTokenManagerInterface $csrfTokenManager = null)
public function __construct(TokenStorageInterface $tokenStorage, AuthenticationManagerInterface $authenticationManager, SessionAuthenticationStrategyInterface $sessionStrategy, HttpUtils $httpUtils, $providerKey, AuthenticationSuccessHandlerInterface $successHandler, AuthenticationFailureHandlerInterface $failureHandler, array $options = [], LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null, CsrfTokenManagerInterface $csrfTokenManager = null)
{
parent::__construct($tokenStorage, $authenticationManager, $sessionStrategy, $httpUtils, $providerKey, $successHandler, $failureHandler, array_merge(array(
parent::__construct($tokenStorage, $authenticationManager, $sessionStrategy, $httpUtils, $providerKey, $successHandler, $failureHandler, array_merge([
'username_parameter' => '_username',
'password_parameter' => '_password',
'csrf_parameter' => '_csrf_token',
'csrf_token_id' => 'authenticate',
'post_only' => true,
), $options), $logger, $dispatcher);
], $options), $logger, $dispatcher);
$this->csrfTokenManager = $csrfTokenManager;
}
@@ -77,14 +78,20 @@ class UsernamePasswordFormAuthenticationListener extends AbstractAuthenticationL
}
if ($this->options['post_only']) {
$username = trim(ParameterBagUtils::getParameterBagValue($request->request, $this->options['username_parameter']));
$username = ParameterBagUtils::getParameterBagValue($request->request, $this->options['username_parameter']);
$password = ParameterBagUtils::getParameterBagValue($request->request, $this->options['password_parameter']);
} else {
$username = trim(ParameterBagUtils::getRequestParameterValue($request, $this->options['username_parameter']));
$username = ParameterBagUtils::getRequestParameterValue($request, $this->options['username_parameter']);
$password = ParameterBagUtils::getRequestParameterValue($request, $this->options['password_parameter']);
}
if (strlen($username) > Security::MAX_USERNAME_LENGTH) {
if (!\is_string($username) && (!\is_object($username) || !method_exists($username, '__toString'))) {
throw new BadRequestHttpException(sprintf('The key "%s" must be a string, "%s" given.', $this->options['username_parameter'], \gettype($username)));
}
$username = trim($username);
if (\strlen($username) > Security::MAX_USERNAME_LENGTH) {
throw new BadCredentialsException('Invalid username.');
}
@@ -11,12 +11,12 @@
namespace Symfony\Component\Security\Http\Firewall;
use Psr\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
/**
* X509 authentication listener.
@@ -44,14 +44,17 @@ class X509AuthenticationListener extends AbstractPreAuthenticatedListener
$user = null;
if ($request->server->has($this->userKey)) {
$user = $request->server->get($this->userKey);
} elseif ($request->server->has($this->credentialKey) && preg_match('#/emailAddress=(.+\@.+\..+)(/|$)#', $request->server->get($this->credentialKey), $matches)) {
} elseif (
$request->server->has($this->credentialKey)
&& preg_match('#emailAddress=([^,/@]++@[^,/]++)#', $request->server->get($this->credentialKey), $matches)
) {
$user = $matches[1];
}
if (null === $user) {
throw new BadCredentialsException(sprintf('SSL credentials not found: %s, %s', $this->userKey, $this->credentialKey));
throw new BadCredentialsException(sprintf('SSL credentials not found: "%s", "%s".', $this->userKey, $this->credentialKey));
}
return array($user, $request->server->get($this->credentialKey, ''));
return [$user, $request->server->get($this->credentialKey, '')];
}
}