+ */
+abstract class AbstractListener
+{
+ final public function __invoke(RequestEvent $event)
+ {
+ if (false !== $this->supports($event->getRequest())) {
+ $this->authenticate($event);
+ }
+ }
+
+ /**
+ * Tells whether the authenticate() method should be called or not depending on the incoming request.
+ *
+ * Returning null means authenticate() can be called lazily when accessing the token storage.
+ */
+ abstract public function supports(Request $request): ?bool;
+
+ /**
+ * Does whatever is required to authenticate the request, typically calling $event->setResponse() internally.
+ */
+ abstract public function authenticate(RequestEvent $event);
+}
diff --git a/src/Symfony/Component/Security/Http/Firewall/AbstractPreAuthenticatedListener.php b/src/Symfony/Component/Security/Http/Firewall/AbstractPreAuthenticatedListener.php
index b969ae3bdb..fbf1d7557f 100644
--- a/src/Symfony/Component/Security/Http/Firewall/AbstractPreAuthenticatedListener.php
+++ b/src/Symfony/Component/Security/Http/Firewall/AbstractPreAuthenticatedListener.php
@@ -34,8 +34,8 @@ use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
*
* @internal
*/
-abstract class AbstractPreAuthenticatedListener
-{
+abstract class AbstractPreAuthenticatedListener extends AbstractListener
+
protected $logger;
private $tokenStorage;
private $authenticationManager;
@@ -53,20 +53,31 @@ abstract class AbstractPreAuthenticatedListener
}
/**
- * Handles pre-authentication.
+ * {@inheritdoc}
*/
- public function __invoke(RequestEvent $event)
+ public function supports(Request $request): ?bool
{
- $request = $event->getRequest();
-
try {
- list($user, $credentials) = $this->getPreAuthenticatedData($request);
+ $request->attributes->set('_pre_authenticated_data', $this->getPreAuthenticatedData($request));
} catch (BadCredentialsException $e) {
$this->clearToken($e);
- return;
+ return false;
}
+ return true;
+ }
+
+ /**
+ * Handles pre-authentication.
+ */
+ public function authenticate(RequestEvent $event)
+ {
+ $request = $event->getRequest();
+
+ [$user, $credentials] = $request->attributes->get('_pre_authenticated_data');
+ $request->attributes->remove('_pre_authenticated_data');
+
if (null !== $this->logger) {
$this->logger->debug('Checking current security token.', ['token' => (string) $this->tokenStorage->getToken()]);
}
diff --git a/src/Symfony/Component/Security/Http/Firewall/AccessListener.php b/src/Symfony/Component/Security/Http/Firewall/AccessListener.php
index 2dbeee1033..3d88103d39 100644
--- a/src/Symfony/Component/Security/Http/Firewall/AccessListener.php
+++ b/src/Symfony/Component/Security/Http/Firewall/AccessListener.php
@@ -11,10 +11,12 @@
namespace Symfony\Component\Security\Http\Firewall;
+use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;
+use Symfony\Component\Security\Core\Authorization\Voter\AuthenticatedVoter;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException;
use Symfony\Component\Security\Http\AccessMapInterface;
@@ -27,7 +29,7 @@ use Symfony\Component\Security\Http\Event\LazyResponseEvent;
*
* @final
*/
-class AccessListener
+class AccessListener extends AbstractListener
{
private $tokenStorage;
private $accessDecisionManager;
@@ -42,13 +44,24 @@ class AccessListener
$this->authManager = $authManager;
}
+ /**
+ * {@inheritdoc}
+ */
+ public function supports(Request $request): ?bool
+ {
+ [$attributes] = $this->map->getPatterns($request);
+ $request->attributes->set('_access_control_attributes', $attributes);
+
+ return $attributes && [AuthenticatedVoter::IS_AUTHENTICATED_ANONYMOUSLY] !== $attributes ? true : null;
+ }
+
/**
* Handles access authorization.
*
* @throws AccessDeniedException
* @throws AuthenticationCredentialsNotFoundException
*/
- public function __invoke(RequestEvent $event)
+ public function authenticate(RequestEvent $event)
{
if (!$event instanceof LazyResponseEvent && null === $token = $this->tokenStorage->getToken()) {
throw new AuthenticationCredentialsNotFoundException('A Token was not found in the TokenStorage.');
@@ -56,9 +69,10 @@ class AccessListener
$request = $event->getRequest();
- list($attributes) = $this->map->getPatterns($request);
+ $attributes = $request->attributes->get('_access_control_attributes');
+ $request->attributes->remove('_access_control_attributes');
- if (!$attributes) {
+ if (!$attributes || ([AuthenticatedVoter::IS_AUTHENTICATED_ANONYMOUSLY] === $attributes && $event instanceof LazyResponseEvent)) {
return;
}
diff --git a/src/Symfony/Component/Security/Http/Firewall/AnonymousAuthenticationListener.php b/src/Symfony/Component/Security/Http/Firewall/AnonymousAuthenticationListener.php
index f9f0ff0946..c54e6ba67d 100644
--- a/src/Symfony/Component/Security/Http/Firewall/AnonymousAuthenticationListener.php
+++ b/src/Symfony/Component/Security/Http/Firewall/AnonymousAuthenticationListener.php
@@ -12,6 +12,7 @@
namespace Symfony\Component\Security\Http\Firewall;
use Psr\Log\LoggerInterface;
+use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken;
@@ -26,7 +27,7 @@ use Symfony\Component\Security\Core\Exception\AuthenticationException;
*
* @final
*/
-class AnonymousAuthenticationListener
+class AnonymousAuthenticationListener extends AbstractListener
{
private $tokenStorage;
private $secret;
@@ -41,10 +42,18 @@ class AnonymousAuthenticationListener
$this->logger = $logger;
}
+ /**
+ * {@inheritdoc}
+ */
+ public function supports(Request $request): ?bool
+ {
+ return null; // always run authenticate() lazily with lazy firewalls
+ }
+
/**
* Handles anonymous authentication.
*/
- public function __invoke(RequestEvent $event)
+ public function authenticate(RequestEvent $event)
{
if (null !== $this->tokenStorage->getToken()) {
return;
diff --git a/src/Symfony/Component/Security/Http/Firewall/BasicAuthenticationListener.php b/src/Symfony/Component/Security/Http/Firewall/BasicAuthenticationListener.php
index 77c4f9dac9..0692e055d0 100644
--- a/src/Symfony/Component/Security/Http/Firewall/BasicAuthenticationListener.php
+++ b/src/Symfony/Component/Security/Http/Firewall/BasicAuthenticationListener.php
@@ -29,7 +29,7 @@ use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterfa
*
* @final
*/
-class BasicAuthenticationListener
+class BasicAuthenticationListener extends AbstractListener
{
private $tokenStorage;
private $authenticationManager;
@@ -53,10 +53,18 @@ class BasicAuthenticationListener
$this->ignoreFailure = false;
}
+ /**
+ * {@inheritdoc}
+ */
+ public function supports(Request $request): ?bool
+ {
+ return null !== $request->headers->get('PHP_AUTH_USER');
+ }
+
/**
* Handles basic authentication.
*/
- public function __invoke(RequestEvent $event)
+ public function authenticate(RequestEvent $event)
{
$request = $event->getRequest();
diff --git a/src/Symfony/Component/Security/Http/Firewall/ChannelListener.php b/src/Symfony/Component/Security/Http/Firewall/ChannelListener.php
index 94515061de..243faecbc0 100644
--- a/src/Symfony/Component/Security/Http/Firewall/ChannelListener.php
+++ b/src/Symfony/Component/Security/Http/Firewall/ChannelListener.php
@@ -12,6 +12,7 @@
namespace Symfony\Component\Security\Http\Firewall;
use Psr\Log\LoggerInterface;
+use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\Security\Http\AccessMapInterface;
use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface;
@@ -24,7 +25,7 @@ use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface
*
* @final
*/
-class ChannelListener
+class ChannelListener extends AbstractListener
{
private $map;
private $authenticationEntryPoint;
@@ -40,10 +41,8 @@ class ChannelListener
/**
* Handles channel management.
*/
- public function __invoke(RequestEvent $event)
+ public function supports(Request $request): ?bool
{
- $request = $event->getRequest();
-
list(, $channel) = $this->map->getPatterns($request);
if ('https' === $channel && !$request->isSecure()) {
@@ -57,11 +56,7 @@ class ChannelListener
}
}
- $response = $this->authenticationEntryPoint->start($request);
-
- $event->setResponse($response);
-
- return;
+ return true;
}
if ('http' === $channel && $request->isSecure()) {
@@ -69,9 +64,18 @@ class ChannelListener
$this->logger->info('Redirecting to HTTP.');
}
- $response = $this->authenticationEntryPoint->start($request);
-
- $event->setResponse($response);
+ return true;
}
+
+ return false;
+ }
+
+ public function authenticate(RequestEvent $event)
+ {
+ $request = $event->getRequest();
+
+ $response = $this->authenticationEntryPoint->start($request);
+
+ $event->setResponse($response);
}
}
diff --git a/src/Symfony/Component/Security/Http/Firewall/ContextListener.php b/src/Symfony/Component/Security/Http/Firewall/ContextListener.php
index b9f5809723..3680345772 100644
--- a/src/Symfony/Component/Security/Http/Firewall/ContextListener.php
+++ b/src/Symfony/Component/Security/Http/Firewall/ContextListener.php
@@ -29,6 +29,7 @@ use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Http\Event\DeauthenticatedEvent;
+use Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
/**
@@ -39,7 +40,7 @@ use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
*
* @final
*/
-class ContextListener
+class ContextListener extends AbstractListener
{
private $tokenStorage;
private $sessionKey;
@@ -48,6 +49,7 @@ class ContextListener
private $dispatcher;
private $registered;
private $trustResolver;
+ private $rememberMeServices;
private $sessionTrackerEnabler;
/**
@@ -68,10 +70,18 @@ class ContextListener
$this->sessionTrackerEnabler = $sessionTrackerEnabler;
}
+ /**
+ * {@inheritdoc}
+ */
+ public function supports(Request $request): ?bool
+ {
+ return null; // always run authenticate() lazily with lazy firewalls
+ }
+
/**
* Reads the Security Token from the session.
*/
- public function __invoke(RequestEvent $event)
+ public function authenticate(RequestEvent $event)
{
if (!$this->registered && null !== $this->dispatcher && $event->isMasterRequest()) {
$this->dispatcher->addListener(KernelEvents::RESPONSE, [$this, 'onKernelResponse']);
@@ -112,6 +122,10 @@ class ContextListener
if ($token instanceof TokenInterface) {
$token = $this->refreshUser($token);
+
+ if (!$token && $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.', ['key' => $this->sessionKey, 'received' => $token]);
@@ -282,4 +296,9 @@ class ContextListener
{
throw new \ErrorException('Class not found: '.$class, 0x37313bc);
}
+
+ public function setRememberMeServices(RememberMeServicesInterface $rememberMeServices)
+ {
+ $this->rememberMeServices = $rememberMeServices;
+ }
}
diff --git a/src/Symfony/Component/Security/Http/Firewall/LogoutListener.php b/src/Symfony/Component/Security/Http/Firewall/LogoutListener.php
index 46f757e1ee..1194cea95f 100644
--- a/src/Symfony/Component/Security/Http/Firewall/LogoutListener.php
+++ b/src/Symfony/Component/Security/Http/Firewall/LogoutListener.php
@@ -30,7 +30,7 @@ use Symfony\Component\Security\Http\ParameterBagUtils;
*
* @final
*/
-class LogoutListener
+class LogoutListener extends AbstractListener
{
private $tokenStorage;
private $options;
@@ -61,6 +61,14 @@ class LogoutListener
$this->handlers[] = $handler;
}
+ /**
+ * {@inheritdoc}
+ */
+ public function supports(Request $request): ?bool
+ {
+ return $this->requiresLogout($request);
+ }
+
/**
* Performs the logout if requested.
*
@@ -70,14 +78,10 @@ class LogoutListener
* @throws LogoutException if the CSRF token is invalid
* @throws \RuntimeException if the LogoutSuccessHandlerInterface instance does not return a response
*/
- public function __invoke(RequestEvent $event)
+ public function authenticate(RequestEvent $event)
{
$request = $event->getRequest();
- if (!$this->requiresLogout($request)) {
- return;
- }
-
if (null !== $this->csrfTokenManager) {
$csrfToken = ParameterBagUtils::getRequestParameterValue($request, $this->options['csrf_parameter']);
diff --git a/src/Symfony/Component/Security/Http/Firewall/RememberMeListener.php b/src/Symfony/Component/Security/Http/Firewall/RememberMeListener.php
index 2d0626d05c..c288fcb94b 100644
--- a/src/Symfony/Component/Security/Http/Firewall/RememberMeListener.php
+++ b/src/Symfony/Component/Security/Http/Firewall/RememberMeListener.php
@@ -12,6 +12,7 @@
namespace Symfony\Component\Security\Http\Firewall;
use Psr\Log\LoggerInterface;
+use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
@@ -30,7 +31,7 @@ use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
*
* @final
*/
-class RememberMeListener
+class RememberMeListener extends AbstractListener
{
private $tokenStorage;
private $rememberMeServices;
@@ -51,10 +52,18 @@ class RememberMeListener
$this->sessionStrategy = null === $sessionStrategy ? new SessionAuthenticationStrategy(SessionAuthenticationStrategy::MIGRATE) : $sessionStrategy;
}
+ /**
+ * {@inheritdoc}
+ */
+ public function supports(Request $request): ?bool
+ {
+ return null; // always run authenticate() lazily with lazy firewalls
+ }
+
/**
* Handles remember-me cookie based authentication.
*/
- public function __invoke(RequestEvent $event)
+ public function authenticate(RequestEvent $event)
{
if (null !== $this->tokenStorage->getToken()) {
return;
diff --git a/src/Symfony/Component/Security/Http/Firewall/SwitchUserListener.php b/src/Symfony/Component/Security/Http/Firewall/SwitchUserListener.php
index 6eaee110d0..f6d4c8a587 100644
--- a/src/Symfony/Component/Security/Http/Firewall/SwitchUserListener.php
+++ b/src/Symfony/Component/Security/Http/Firewall/SwitchUserListener.php
@@ -37,7 +37,7 @@ use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
*
* @final
*/
-class SwitchUserListener
+class SwitchUserListener extends AbstractListener
{
const EXIT_VALUE = '_exit';
@@ -71,14 +71,10 @@ class SwitchUserListener
}
/**
- * Handles the switch to another user.
- *
- * @throws \LogicException if switching to a user failed
+ * {@inheritdoc}
*/
- public function __invoke(RequestEvent $event)
+ public function supports(Request $request): ?bool
{
- $request = $event->getRequest();
-
// usernames can be falsy
$username = $request->get($this->usernameParameter);
@@ -88,9 +84,26 @@ class SwitchUserListener
// if it's still "empty", nothing to do.
if (null === $username || '' === $username) {
- return;
+ return false;
}
+ $request->attributes->set('_switch_user_username', $username);
+
+ return true;
+ }
+
+ /**
+ * Handles the switch to another user.
+ *
+ * @throws \LogicException if switching to a user failed
+ */
+ public function authenticate(RequestEvent $event)
+ {
+ $request = $event->getRequest();
+
+ $username = $request->attributes->get('_switch_user_username');
+ $request->attributes->remove('_switch_user_username');
+
if (null === $this->tokenStorage->getToken()) {
throw new AuthenticationCredentialsNotFoundException('Could not find original Token object.');
}
diff --git a/src/Symfony/Component/Security/Http/Firewall/UsernamePasswordJsonAuthenticationListener.php b/src/Symfony/Component/Security/Http/Firewall/UsernamePasswordJsonAuthenticationListener.php
index 5c5a35e435..ace15f03d5 100644
--- a/src/Symfony/Component/Security/Http/Firewall/UsernamePasswordJsonAuthenticationListener.php
+++ b/src/Symfony/Component/Security/Http/Firewall/UsernamePasswordJsonAuthenticationListener.php
@@ -43,7 +43,7 @@ use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
*
* @final
*/
-class UsernamePasswordJsonAuthenticationListener
+class UsernamePasswordJsonAuthenticationListener extends AbstractListener
{
private $tokenStorage;
private $authenticationManager;
@@ -71,19 +71,27 @@ class UsernamePasswordJsonAuthenticationListener
$this->propertyAccessor = $propertyAccessor ?: PropertyAccess::createPropertyAccessor();
}
- public function __invoke(RequestEvent $event)
+ public function supports(Request $request): ?bool
{
- $request = $event->getRequest();
if (false === strpos($request->getRequestFormat(), 'json')
&& false === strpos($request->getContentType(), 'json')
) {
- return;
+ return false;
}
if (isset($this->options['check_path']) && !$this->httpUtils->checkRequestPath($request, $this->options['check_path'])) {
- return;
+ return false;
}
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function authenticate(RequestEvent $event)
+ {
+ $request = $event->getRequest();
$data = json_decode($request->getContent());
try {
diff --git a/src/Symfony/Component/Security/Http/Tests/Firewall/AccessListenerTest.php b/src/Symfony/Component/Security/Http/Tests/Firewall/AccessListenerTest.php
index 1dff48dfda..168e256437 100644
--- a/src/Symfony/Component/Security/Http/Tests/Firewall/AccessListenerTest.php
+++ b/src/Symfony/Component/Security/Http/Tests/Firewall/AccessListenerTest.php
@@ -14,6 +14,7 @@ namespace Symfony\Component\Security\Http\Tests\Firewall;
use PHPUnit\Framework\TestCase;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Event\RequestEvent;
+use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;
@@ -26,7 +27,7 @@ class AccessListenerTest extends TestCase
public function testHandleWhenTheAccessDecisionManagerDecidesToRefuseAccess()
{
$this->expectException('Symfony\Component\Security\Core\Exception\AccessDeniedException');
- $request = $this->getMockBuilder('Symfony\Component\HttpFoundation\Request')->disableOriginalConstructor()->disableOriginalClone()->getMock();
+ $request = new Request();
$accessMap = $this->getMockBuilder('Symfony\Component\Security\Http\AccessMapInterface')->getMock();
$accessMap
@@ -65,19 +66,12 @@ class AccessListenerTest extends TestCase
$this->getMockBuilder('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface')->getMock()
);
- $event = $this->getMockBuilder(RequestEvent::class)->disableOriginalConstructor()->getMock();
- $event
- ->expects($this->any())
- ->method('getRequest')
- ->willReturn($request)
- ;
-
- $listener($event);
+ $listener(new RequestEvent($this->createMock(HttpKernelInterface::class), $request, HttpKernelInterface::MASTER_REQUEST));
}
public function testHandleWhenTheTokenIsNotAuthenticated()
{
- $request = $this->getMockBuilder('Symfony\Component\HttpFoundation\Request')->disableOriginalConstructor()->disableOriginalClone()->getMock();
+ $request = new Request();
$accessMap = $this->getMockBuilder('Symfony\Component\Security\Http\AccessMapInterface')->getMock();
$accessMap
@@ -136,19 +130,12 @@ class AccessListenerTest extends TestCase
$authManager
);
- $event = $this->getMockBuilder(RequestEvent::class)->disableOriginalConstructor()->getMock();
- $event
- ->expects($this->any())
- ->method('getRequest')
- ->willReturn($request)
- ;
-
- $listener($event);
+ $listener(new RequestEvent($this->createMock(HttpKernelInterface::class), $request, HttpKernelInterface::MASTER_REQUEST));
}
public function testHandleWhenThereIsNoAccessMapEntryMatchingTheRequest()
{
- $request = $this->getMockBuilder('Symfony\Component\HttpFoundation\Request')->disableOriginalConstructor()->disableOriginalClone()->getMock();
+ $request = new Request();
$accessMap = $this->getMockBuilder('Symfony\Component\Security\Http\AccessMapInterface')->getMock();
$accessMap
@@ -178,19 +165,12 @@ class AccessListenerTest extends TestCase
$this->getMockBuilder('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface')->getMock()
);
- $event = $this->getMockBuilder(RequestEvent::class)->disableOriginalConstructor()->getMock();
- $event
- ->expects($this->any())
- ->method('getRequest')
- ->willReturn($request)
- ;
-
- $listener($event);
+ $listener(new RequestEvent($this->createMock(HttpKernelInterface::class), $request, HttpKernelInterface::MASTER_REQUEST));
}
public function testHandleWhenAccessMapReturnsEmptyAttributes()
{
- $request = $this->getMockBuilder(Request::class)->disableOriginalConstructor()->disableOriginalClone()->getMock();
+ $request = new Request();
$accessMap = $this->getMockBuilder(AccessMapInterface::class)->getMock();
$accessMap
@@ -213,12 +193,7 @@ class AccessListenerTest extends TestCase
$this->getMockBuilder(AuthenticationManagerInterface::class)->getMock()
);
- $event = $this->getMockBuilder(RequestEvent::class)->disableOriginalConstructor()->getMock();
- $event
- ->expects($this->any())
- ->method('getRequest')
- ->willReturn($request)
- ;
+ $event = new RequestEvent($this->createMock(HttpKernelInterface::class), $request, HttpKernelInterface::MASTER_REQUEST);
$listener(new LazyResponseEvent($event));
}
@@ -233,7 +208,7 @@ class AccessListenerTest extends TestCase
->willReturn(null)
;
- $request = $this->getMockBuilder(Request::class)->disableOriginalConstructor()->disableOriginalClone()->getMock();
+ $request = new Request();
$accessMap = $this->getMockBuilder(AccessMapInterface::class)->getMock();
$accessMap
@@ -250,13 +225,6 @@ class AccessListenerTest extends TestCase
$this->getMockBuilder('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface')->getMock()
);
- $event = $this->getMockBuilder(RequestEvent::class)->disableOriginalConstructor()->getMock();
- $event
- ->expects($this->any())
- ->method('getRequest')
- ->willReturn($request)
- ;
-
- $listener($event);
+ $listener(new RequestEvent($this->createMock(HttpKernelInterface::class), $request, HttpKernelInterface::MASTER_REQUEST));
}
}
diff --git a/src/Symfony/Component/Security/Http/Tests/Firewall/AnonymousAuthenticationListenerTest.php b/src/Symfony/Component/Security/Http/Tests/Firewall/AnonymousAuthenticationListenerTest.php
index 47f09199c4..e6f9f42217 100644
--- a/src/Symfony/Component/Security/Http/Tests/Firewall/AnonymousAuthenticationListenerTest.php
+++ b/src/Symfony/Component/Security/Http/Tests/Firewall/AnonymousAuthenticationListenerTest.php
@@ -12,7 +12,9 @@
namespace Symfony\Component\Security\Http\Tests\Firewall;
use PHPUnit\Framework\TestCase;
+use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Event\RequestEvent;
+use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken;
use Symfony\Component\Security\Http\Firewall\AnonymousAuthenticationListener;
@@ -38,7 +40,7 @@ class AnonymousAuthenticationListenerTest extends TestCase
;
$listener = new AnonymousAuthenticationListener($tokenStorage, 'TheSecret', null, $authenticationManager);
- $listener($this->getMockBuilder(RequestEvent::class)->disableOriginalConstructor()->getMock());
+ $listener(new RequestEvent($this->createMock(HttpKernelInterface::class), new Request(), HttpKernelInterface::MASTER_REQUEST));
}
public function testHandleWithTokenStorageHavingNoToken()
@@ -69,7 +71,7 @@ class AnonymousAuthenticationListenerTest extends TestCase
;
$listener = new AnonymousAuthenticationListener($tokenStorage, 'TheSecret', null, $authenticationManager);
- $listener($this->getMockBuilder(RequestEvent::class)->disableOriginalConstructor()->getMock());
+ $listener(new RequestEvent($this->createMock(HttpKernelInterface::class), new Request(), HttpKernelInterface::MASTER_REQUEST));
}
public function testHandledEventIsLogged()
@@ -84,6 +86,6 @@ class AnonymousAuthenticationListenerTest extends TestCase
$authenticationManager = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface')->getMock();
$listener = new AnonymousAuthenticationListener($tokenStorage, 'TheSecret', $logger, $authenticationManager);
- $listener($this->getMockBuilder(RequestEvent::class)->disableOriginalConstructor()->getMock());
+ $listener(new RequestEvent($this->createMock(HttpKernelInterface::class), new Request(), HttpKernelInterface::MASTER_REQUEST));
}
}
diff --git a/src/Symfony/Component/Security/Http/Tests/Firewall/ContextListenerTest.php b/src/Symfony/Component/Security/Http/Tests/Firewall/ContextListenerTest.php
index 3432bd7f97..ba6dbfc262 100644
--- a/src/Symfony/Component/Security/Http/Tests/Firewall/ContextListenerTest.php
+++ b/src/Symfony/Component/Security/Http/Tests/Firewall/ContextListenerTest.php
@@ -36,6 +36,7 @@ use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Http\Event\DeauthenticatedEvent;
use Symfony\Component\Security\Http\Firewall\ContextListener;
+use Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface;
use Symfony\Contracts\Service\ServiceLocatorTrait;
class ContextListenerTest extends TestCase
@@ -262,10 +263,23 @@ class ContextListenerTest extends TestCase
$tokenStorage = new TokenStorage();
$badRefreshedUser = new User('foobar', 'baz');
$goodRefreshedUser = new User('foobar', 'bar');
- $tokenStorage = $this->handleEventWithPreviousSession([new SupportingUserProvider($badRefreshedUser), new SupportingUserProvider($goodRefreshedUser)], $goodRefreshedUser, true);
+ $tokenStorage = $this->handleEventWithPreviousSession([new SupportingUserProvider($badRefreshedUser), new SupportingUserProvider($goodRefreshedUser)], $goodRefreshedUser);
$this->assertSame($goodRefreshedUser, $tokenStorage->getToken()->getUser());
}
+ public function testRememberMeGetsCanceledIfTokenIsDeauthenticated()
+ {
+ $tokenStorage = new TokenStorage();
+ $refreshedUser = new User('foobar', 'baz');
+
+ $rememberMeServices = $this->createMock(RememberMeServicesInterface::class);
+ $rememberMeServices->expects($this->once())->method('loginFail');
+
+ $tokenStorage = $this->handleEventWithPreviousSession([new NotSupportingUserProvider(), new SupportingUserProvider($refreshedUser)], null, $rememberMeServices);
+
+ $this->assertNull($tokenStorage->getToken());
+ }
+
public function testTryAllUserProvidersUntilASupportingUserProviderIsFound()
{
$refreshedUser = new User('foobar', 'baz');
@@ -372,7 +386,7 @@ class ContextListenerTest extends TestCase
return $session;
}
- private function handleEventWithPreviousSession($userProviders, UserInterface $user = null)
+ private function handleEventWithPreviousSession($userProviders, UserInterface $user = null, RememberMeServicesInterface $rememberMeServices = null)
{
$user = $user ?: new User('foo', 'bar');
$session = new Session(new MockArraySessionStorage());
@@ -392,6 +406,10 @@ class ContextListenerTest extends TestCase
$sessionTrackerEnabler = [$tokenStorage, 'enableUsageTracking'];
$listener = new ContextListener($tokenStorage, $userProviders, 'context_key', null, null, null, $sessionTrackerEnabler);
+
+ if ($rememberMeServices) {
+ $listener->setRememberMeServices($rememberMeServices);
+ }
$listener(new RequestEvent($this->getMockBuilder(HttpKernelInterface::class)->getMock(), $request, HttpKernelInterface::MASTER_REQUEST));
$this->assertSame($usageIndex, $session->getUsageIndex());
diff --git a/src/Symfony/Component/Security/Http/Tests/Firewall/RememberMeListenerTest.php b/src/Symfony/Component/Security/Http/Tests/Firewall/RememberMeListenerTest.php
index ceb557b139..d321ed6892 100644
--- a/src/Symfony/Component/Security/Http/Tests/Firewall/RememberMeListenerTest.php
+++ b/src/Symfony/Component/Security/Http/Tests/Firewall/RememberMeListenerTest.php
@@ -15,6 +15,7 @@ use PHPUnit\Framework\TestCase;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\Event\ResponseEvent;
+use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Http\Firewall\RememberMeListener;
use Symfony\Component\Security\Http\SecurityEvents;
@@ -27,7 +28,7 @@ class RememberMeListenerTest extends TestCase
list($listener, $tokenStorage) = $this->getListener();
$tokenStorage
- ->expects($this->once())
+ ->expects($this->any())
->method('getToken')
->willReturn($this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')->getMock())
;
@@ -45,7 +46,7 @@ class RememberMeListenerTest extends TestCase
list($listener, $tokenStorage, $service) = $this->getListener();
$tokenStorage
- ->expects($this->once())
+ ->expects($this->any())
->method('getToken')
->willReturn(null)
;
@@ -57,11 +58,6 @@ class RememberMeListenerTest extends TestCase
;
$event = $this->getGetResponseEvent();
- $event
- ->expects($this->once())
- ->method('getRequest')
- ->willReturn(new Request())
- ;
$this->assertNull($listener($event));
}
@@ -73,7 +69,7 @@ class RememberMeListenerTest extends TestCase
$exception = new AuthenticationException('Authentication failed.');
$tokenStorage
- ->expects($this->once())
+ ->expects($this->any())
->method('getToken')
->willReturn(null)
;
@@ -96,12 +92,7 @@ class RememberMeListenerTest extends TestCase
->willThrowException($exception)
;
- $event = $this->getGetResponseEvent();
- $event
- ->expects($this->once())
- ->method('getRequest')
- ->willReturn($request)
- ;
+ $event = $this->getGetResponseEvent($request);
$listener($event);
}
@@ -113,7 +104,7 @@ class RememberMeListenerTest extends TestCase
list($listener, $tokenStorage, $service, $manager) = $this->getListener(false, false);
$tokenStorage
- ->expects($this->once())
+ ->expects($this->any())
->method('getToken')
->willReturn(null)
;
@@ -137,11 +128,6 @@ class RememberMeListenerTest extends TestCase
;
$event = $this->getGetResponseEvent();
- $event
- ->expects($this->once())
- ->method('getRequest')
- ->willReturn(new Request())
- ;
$listener($event);
}
@@ -151,7 +137,7 @@ class RememberMeListenerTest extends TestCase
list($listener, $tokenStorage, $service, $manager) = $this->getListener();
$tokenStorage
- ->expects($this->once())
+ ->expects($this->any())
->method('getToken')
->willReturn(null)
;
@@ -174,11 +160,6 @@ class RememberMeListenerTest extends TestCase
;
$event = $this->getGetResponseEvent();
- $event
- ->expects($this->once())
- ->method('getRequest')
- ->willReturn(new Request())
- ;
$listener($event);
}
@@ -188,7 +169,7 @@ class RememberMeListenerTest extends TestCase
list($listener, $tokenStorage, $service, $manager) = $this->getListener();
$tokenStorage
- ->expects($this->once())
+ ->expects($this->any())
->method('getToken')
->willReturn(null)
;
@@ -213,11 +194,6 @@ class RememberMeListenerTest extends TestCase
;
$event = $this->getGetResponseEvent();
- $event
- ->expects($this->once())
- ->method('getRequest')
- ->willReturn(new Request())
- ;
$listener($event);
}
@@ -227,7 +203,7 @@ class RememberMeListenerTest extends TestCase
list($listener, $tokenStorage, $service, $manager, , , $sessionStrategy) = $this->getListener(false, true, true);
$tokenStorage
- ->expects($this->once())
+ ->expects($this->any())
->method('getToken')
->willReturn(null)
;
@@ -258,25 +234,10 @@ class RememberMeListenerTest extends TestCase
->willReturn(true)
;
- $request = $this->getMockBuilder('\Symfony\Component\HttpFoundation\Request')->getMock();
- $request
- ->expects($this->once())
- ->method('hasSession')
- ->willReturn(true)
- ;
+ $request = new Request();
+ $request->setSession($session);
- $request
- ->expects($this->once())
- ->method('getSession')
- ->willReturn($session)
- ;
-
- $event = $this->getGetResponseEvent();
- $event
- ->expects($this->once())
- ->method('getRequest')
- ->willReturn($request)
- ;
+ $event = $this->getGetResponseEvent($request);
$sessionStrategy
->expects($this->once())
@@ -292,7 +253,7 @@ class RememberMeListenerTest extends TestCase
list($listener, $tokenStorage, $service, $manager) = $this->getListener(false, true, false);
$tokenStorage
- ->expects($this->once())
+ ->expects($this->any())
->method('getToken')
->willReturn(null)
;
@@ -327,25 +288,10 @@ class RememberMeListenerTest extends TestCase
->method('migrate')
;
- $request = $this->getMockBuilder('\Symfony\Component\HttpFoundation\Request')->getMock();
- $request
- ->expects($this->any())
- ->method('hasSession')
- ->willReturn(true)
- ;
+ $request = new Request();
+ $request->setSession($session);
- $request
- ->expects($this->any())
- ->method('getSession')
- ->willReturn($session)
- ;
-
- $event = $this->getGetResponseEvent();
- $event
- ->expects($this->once())
- ->method('getRequest')
- ->willReturn($request)
- ;
+ $event = $this->getGetResponseEvent($request);
$listener($event);
}
@@ -355,7 +301,7 @@ class RememberMeListenerTest extends TestCase
list($listener, $tokenStorage, $service, $manager, , $dispatcher) = $this->getListener(true);
$tokenStorage
- ->expects($this->once())
+ ->expects($this->any())
->method('getToken')
->willReturn(null)
;
@@ -380,12 +326,6 @@ class RememberMeListenerTest extends TestCase
;
$event = $this->getGetResponseEvent();
- $request = new Request();
- $event
- ->expects($this->once())
- ->method('getRequest')
- ->willReturn($request)
- ;
$dispatcher
->expects($this->once())
@@ -399,9 +339,20 @@ class RememberMeListenerTest extends TestCase
$listener($event);
}
- protected function getGetResponseEvent()
+ protected function getGetResponseEvent(Request $request = null): RequestEvent
{
- return $this->getMockBuilder(RequestEvent::class)->disableOriginalConstructor()->getMock();
+ $request = $request ?? new Request();
+
+ $event = $this->getMockBuilder(RequestEvent::class)
+ ->setConstructorArgs([$this->createMock(HttpKernelInterface::class), $request, HttpKernelInterface::MASTER_REQUEST])
+ ->getMock();
+ $event
+ ->expects($this->any())
+ ->method('getRequest')
+ ->willReturn($request)
+ ;
+
+ return $event;
}
protected function getResponseEvent(): ResponseEvent
diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.sl.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.sl.xlf
index 6f5fd98ca1..cb12a8a9da 100644
--- a/src/Symfony/Component/Validator/Resources/translations/validators.sl.xlf
+++ b/src/Symfony/Component/Validator/Resources/translations/validators.sl.xlf
@@ -318,6 +318,54 @@