Merge branch '2.8' into 3.4
* 2.8: fixed CS Avoid migration on stateless firewalls
This commit is contained in:
commit
873abdad12
@ -80,6 +80,7 @@ class GuardAuthenticationFactory implements SecurityFactoryInterface
|
||||
$listener = $container->setDefinition($listenerId, new ChildDefinition('security.authentication.listener.guard'));
|
||||
$listener->replaceArgument(2, $id);
|
||||
$listener->replaceArgument(3, $authenticators);
|
||||
$listener->addMethodCall('setSessionAuthenticationStrategy', array(new Reference('security.authentication.session_strategy.'.$id)));
|
||||
|
||||
// determine the entryPointId to use
|
||||
$entryPointId = $this->determineEntryPoint($defaultEntryPoint, $config);
|
||||
|
@ -41,6 +41,7 @@ class HttpBasicFactory implements SecurityFactoryInterface
|
||||
$listener = $container->setDefinition($listenerId, new ChildDefinition('security.authentication.listener.basic'));
|
||||
$listener->replaceArgument(2, $id);
|
||||
$listener->replaceArgument(3, new Reference($entryPointId));
|
||||
$listener->addMethodCall('setSessionAuthenticationStrategy', array(new Reference('security.authentication.session_strategy.'.$id)));
|
||||
|
||||
return array($provider, $listenerId, $entryPointId);
|
||||
}
|
||||
|
@ -51,6 +51,7 @@ class HttpDigestFactory implements SecurityFactoryInterface
|
||||
$listener->replaceArgument(1, new Reference($userProvider));
|
||||
$listener->replaceArgument(2, $id);
|
||||
$listener->replaceArgument(3, new Reference($entryPointId));
|
||||
$listener->addMethodCall('setSessionAuthenticationStrategy', array(new Reference('security.authentication.session_strategy.'.$id)));
|
||||
|
||||
return array($provider, $listenerId, $entryPointId);
|
||||
}
|
||||
|
@ -38,6 +38,7 @@ class RemoteUserFactory implements SecurityFactoryInterface
|
||||
$listener = $container->setDefinition($listenerId, new ChildDefinition('security.authentication.listener.remote_user'));
|
||||
$listener->replaceArgument(2, $id);
|
||||
$listener->replaceArgument(3, $config['user']);
|
||||
$listener->addMethodCall('setSessionAuthenticationStrategy', array(new Reference('security.authentication.session_strategy.'.$id)));
|
||||
|
||||
return array($providerId, $listenerId, $defaultEntryPoint);
|
||||
}
|
||||
|
@ -57,6 +57,7 @@ class SimplePreAuthenticationFactory implements SecurityFactoryInterface
|
||||
$listener = $container->setDefinition($listenerId, new ChildDefinition('security.authentication.listener.simple_preauth'));
|
||||
$listener->replaceArgument(2, $id);
|
||||
$listener->replaceArgument(3, new Reference($config['authenticator']));
|
||||
$listener->addMethodCall('setSessionAuthenticationStrategy', array(new Reference('security.authentication.session_strategy.'.$id)));
|
||||
|
||||
return array($provider, $listenerId, null);
|
||||
}
|
||||
|
@ -39,6 +39,7 @@ class X509Factory implements SecurityFactoryInterface
|
||||
$listener->replaceArgument(2, $id);
|
||||
$listener->replaceArgument(3, $config['user']);
|
||||
$listener->replaceArgument(4, $config['credentials']);
|
||||
$listener->addMethodCall('setSessionAuthenticationStrategy', array(new Reference('security.authentication.session_strategy.'.$id)));
|
||||
|
||||
return array($providerId, $listenerId, $defaultEntryPoint);
|
||||
}
|
||||
|
@ -62,10 +62,11 @@
|
||||
<service id="security.authentication.session_strategy" class="Symfony\Component\Security\Http\Session\SessionAuthenticationStrategy">
|
||||
<argument>%security.authentication.session_strategy.strategy%</argument>
|
||||
</service>
|
||||
<service id="Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface" alias="security.authentication.session_strategy" />
|
||||
|
||||
<service id="security.authentication.session_strategy_noop" class="Symfony\Component\Security\Http\Session\SessionAuthenticationStrategy" public="false">
|
||||
<argument>none</argument>
|
||||
</service>
|
||||
<service id="Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface" alias="security.authentication.session_strategy" />
|
||||
|
||||
<service id="security.encoder_factory.generic" class="Symfony\Component\Security\Core\Encoder\EncoderFactory">
|
||||
<argument type="collection" />
|
||||
|
@ -20,6 +20,7 @@ use Symfony\Component\Security\Core\Exception\AuthenticationException;
|
||||
use Symfony\Component\Security\Core\User\UserInterface;
|
||||
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
|
||||
use Symfony\Component\Security\Http\SecurityEvents;
|
||||
use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface;
|
||||
|
||||
/**
|
||||
* A utility class that does much of the *work* during the guard authentication process.
|
||||
@ -34,8 +35,8 @@ use Symfony\Component\Security\Http\SecurityEvents;
|
||||
class GuardAuthenticatorHandler
|
||||
{
|
||||
private $tokenStorage;
|
||||
|
||||
private $dispatcher;
|
||||
private $sessionStrategy;
|
||||
|
||||
public function __construct(TokenStorageInterface $tokenStorage, EventDispatcherInterface $eventDispatcher = null)
|
||||
{
|
||||
@ -48,7 +49,7 @@ class GuardAuthenticatorHandler
|
||||
*/
|
||||
public function authenticateWithToken(TokenInterface $token, Request $request)
|
||||
{
|
||||
$this->migrateSession($request);
|
||||
$this->migrateSession($request, $token);
|
||||
$this->tokenStorage->setToken($token);
|
||||
|
||||
if (null !== $this->dispatcher) {
|
||||
@ -131,11 +132,22 @@ class GuardAuthenticatorHandler
|
||||
));
|
||||
}
|
||||
|
||||
private function migrateSession(Request $request)
|
||||
/**
|
||||
* Call this method if your authentication token is stored to a session.
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
public function setSessionAuthenticationStrategy(SessionAuthenticationStrategyInterface $sessionStrategy)
|
||||
{
|
||||
if (!$request->hasSession() || !$request->hasPreviousSession()) {
|
||||
$this->sessionStrategy = $sessionStrategy;
|
||||
}
|
||||
|
||||
private function migrateSession(Request $request, TokenInterface $token)
|
||||
{
|
||||
if (!$this->sessionStrategy || !$request->hasSession() || !$request->hasPreviousSession()) {
|
||||
return;
|
||||
}
|
||||
$request->getSession()->migrate(true);
|
||||
|
||||
$this->sessionStrategy->onAuthentication($request, $token);
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ class GuardAuthenticatorHandlerTest extends TestCase
|
||||
private $dispatcher;
|
||||
private $token;
|
||||
private $request;
|
||||
private $sessionStrategy;
|
||||
private $guardAuthenticator;
|
||||
|
||||
public function testAuthenticateWithToken()
|
||||
@ -118,12 +119,38 @@ class GuardAuthenticatorHandlerTest extends TestCase
|
||||
return $tests;
|
||||
}
|
||||
|
||||
public function testNoFailureIfSessionStrategyNotPassed()
|
||||
{
|
||||
$this->configurePreviousSession();
|
||||
|
||||
$this->tokenStorage->expects($this->once())
|
||||
->method('setToken')
|
||||
->with($this->token);
|
||||
|
||||
$handler = new GuardAuthenticatorHandler($this->tokenStorage, $this->dispatcher);
|
||||
$handler->authenticateWithToken($this->token, $this->request);
|
||||
}
|
||||
|
||||
public function testSessionStrategyIsCalled()
|
||||
{
|
||||
$this->configurePreviousSession();
|
||||
|
||||
$this->sessionStrategy->expects($this->once())
|
||||
->method('onAuthentication')
|
||||
->with($this->request, $this->token);
|
||||
|
||||
$handler = new GuardAuthenticatorHandler($this->tokenStorage, $this->dispatcher);
|
||||
$handler->setSessionAuthenticationStrategy($this->sessionStrategy);
|
||||
$handler->authenticateWithToken($this->token, $this->request);
|
||||
}
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
$this->tokenStorage = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface')->getMock();
|
||||
$this->dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcherInterface')->getMock();
|
||||
$this->token = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')->getMock();
|
||||
$this->request = new Request(array(), array(), array(), array(), array(), array());
|
||||
$this->sessionStrategy = $this->getMockBuilder('Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface')->getMock();
|
||||
$this->guardAuthenticator = $this->getMockBuilder(AuthenticatorInterface::class)->getMock();
|
||||
}
|
||||
|
||||
@ -135,4 +162,14 @@ class GuardAuthenticatorHandlerTest extends TestCase
|
||||
$this->request = null;
|
||||
$this->guardAuthenticator = null;
|
||||
}
|
||||
|
||||
private function configurePreviousSession()
|
||||
{
|
||||
$session = $this->getMockBuilder('Symfony\Component\HttpFoundation\Session\SessionInterface')->getMock();
|
||||
$session->expects($this->any())
|
||||
->method('getName')
|
||||
->willReturn('test_session_name');
|
||||
$this->request->setSession($session);
|
||||
$this->request->cookies->set('test_session_name', 'session_cookie_val');
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ namespace Symfony\Component\Security\Http\Firewall;
|
||||
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\Http\Event\InteractiveLoginEvent;
|
||||
use Symfony\Component\Security\Http\SecurityEvents;
|
||||
@ -22,6 +23,7 @@ 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)
|
||||
{
|
||||
@ -83,7 +86,7 @@ abstract class AbstractPreAuthenticatedListener implements ListenerInterface
|
||||
$this->logger->info('Pre-authentication successful.', array('token' => (string) $token));
|
||||
}
|
||||
|
||||
$this->migrateSession($request);
|
||||
$this->migrateSession($request, $token);
|
||||
|
||||
$this->tokenStorage->setToken($token);
|
||||
|
||||
@ -96,6 +99,16 @@ abstract class AbstractPreAuthenticatedListener implements ListenerInterface
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Call this method if your authentication token is stored to a session.
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
public function setSessionAuthenticationStrategy(SessionAuthenticationStrategyInterface $sessionStrategy)
|
||||
{
|
||||
$this->sessionStrategy = $sessionStrategy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears a PreAuthenticatedToken for this provider (if present).
|
||||
*/
|
||||
@ -118,11 +131,12 @@ abstract class AbstractPreAuthenticatedListener implements ListenerInterface
|
||||
*/
|
||||
abstract protected function getPreAuthenticatedData(Request $request);
|
||||
|
||||
private function migrateSession(Request $request)
|
||||
private function migrateSession(Request $request, TokenInterface $token)
|
||||
{
|
||||
if (!$request->hasSession() || !$request->hasPreviousSession()) {
|
||||
if (!$this->sessionStrategy || !$request->hasSession() || !$request->hasPreviousSession()) {
|
||||
return;
|
||||
}
|
||||
$request->getSession()->migrate(true);
|
||||
|
||||
$this->sessionStrategy->onAuthentication($request, $token);
|
||||
}
|
||||
}
|
||||
|
@ -14,11 +14,13 @@ namespace Symfony\Component\Security\Http\Firewall;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
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\Http\EntryPoint\AuthenticationEntryPointInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
|
||||
use Symfony\Component\Security\Core\Exception\AuthenticationException;
|
||||
use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface;
|
||||
|
||||
/**
|
||||
* BasicAuthenticationListener implements Basic HTTP authentication.
|
||||
@ -33,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)
|
||||
{
|
||||
@ -72,7 +75,7 @@ class BasicAuthenticationListener implements ListenerInterface
|
||||
try {
|
||||
$token = $this->authenticationManager->authenticate(new UsernamePasswordToken($username, $request->headers->get('PHP_AUTH_PW'), $this->providerKey));
|
||||
|
||||
$this->migrateSession($request);
|
||||
$this->migrateSession($request, $token);
|
||||
|
||||
$this->tokenStorage->setToken($token);
|
||||
} catch (AuthenticationException $e) {
|
||||
@ -93,11 +96,22 @@ class BasicAuthenticationListener implements ListenerInterface
|
||||
}
|
||||
}
|
||||
|
||||
private function migrateSession(Request $request)
|
||||
/**
|
||||
* Call this method if your authentication token is stored to a session.
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
public function setSessionAuthenticationStrategy(SessionAuthenticationStrategyInterface $sessionStrategy)
|
||||
{
|
||||
if (!$request->hasSession() || !$request->hasPreviousSession()) {
|
||||
$this->sessionStrategy = $sessionStrategy;
|
||||
}
|
||||
|
||||
private function migrateSession(Request $request, TokenInterface $token)
|
||||
{
|
||||
if (!$this->sessionStrategy || !$request->hasSession() || !$request->hasPreviousSession()) {
|
||||
return;
|
||||
}
|
||||
$request->getSession()->migrate(true);
|
||||
|
||||
$this->sessionStrategy->onAuthentication($request, $token);
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
namespace Symfony\Component\Security\Http\Firewall;
|
||||
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
use Symfony\Component\Security\Core\User\UserProviderInterface;
|
||||
use Symfony\Component\Security\Http\EntryPoint\DigestAuthenticationEntryPoint;
|
||||
use Psr\Log\LoggerInterface;
|
||||
@ -23,6 +24,7 @@ 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.
|
||||
@ -38,6 +40,7 @@ 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)
|
||||
{
|
||||
@ -121,9 +124,20 @@ class DigestAuthenticationListener implements ListenerInterface
|
||||
$this->logger->info('Digest authentication successful.', array('username' => $digestAuth->getUsername(), 'received' => $digestAuth->getResponse()));
|
||||
}
|
||||
|
||||
$this->migrateSession($request);
|
||||
$token = new UsernamePasswordToken($user, $user->getPassword(), $this->providerKey);
|
||||
$this->migrateSession($request, $token);
|
||||
|
||||
$this->tokenStorage->setToken(new UsernamePasswordToken($user, $user->getPassword(), $this->providerKey));
|
||||
$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)
|
||||
@ -140,12 +154,13 @@ class DigestAuthenticationListener implements ListenerInterface
|
||||
$event->setResponse($this->authenticationEntryPoint->start($request, $authException));
|
||||
}
|
||||
|
||||
private function migrateSession(Request $request)
|
||||
private function migrateSession(Request $request, TokenInterface $token)
|
||||
{
|
||||
if (!$request->hasSession() || !$request->hasPreviousSession()) {
|
||||
if (!$this->sessionStrategy || !$request->hasSession() || !$request->hasPreviousSession()) {
|
||||
return;
|
||||
}
|
||||
$request->getSession()->migrate(true);
|
||||
|
||||
$this->sessionStrategy->onAuthentication($request, $token);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -19,12 +19,14 @@ use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Security\Http\Authentication\SimplePreAuthenticatorInterface;
|
||||
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\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.
|
||||
@ -39,6 +41,7 @@ class SimplePreAuthenticationListener implements ListenerInterface
|
||||
private $simpleAuthenticator;
|
||||
private $logger;
|
||||
private $dispatcher;
|
||||
private $sessionStrategy;
|
||||
|
||||
/**
|
||||
* @param TokenStorageInterface $tokenStorage A TokenStorageInterface instance
|
||||
@ -62,6 +65,16 @@ class SimplePreAuthenticationListener implements ListenerInterface
|
||||
$this->dispatcher = $dispatcher;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call this method if your authentication token is stored to a session.
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
public function setSessionAuthenticationStrategy(SessionAuthenticationStrategyInterface $sessionStrategy)
|
||||
{
|
||||
$this->sessionStrategy = $sessionStrategy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles basic authentication.
|
||||
*/
|
||||
@ -87,7 +100,7 @@ class SimplePreAuthenticationListener implements ListenerInterface
|
||||
|
||||
$token = $this->authenticationManager->authenticate($token);
|
||||
|
||||
$this->migrateSession($request);
|
||||
$this->migrateSession($request, $token);
|
||||
|
||||
$this->tokenStorage->setToken($token);
|
||||
|
||||
@ -124,11 +137,12 @@ class SimplePreAuthenticationListener implements ListenerInterface
|
||||
}
|
||||
}
|
||||
|
||||
private function migrateSession(Request $request)
|
||||
private function migrateSession(Request $request, TokenInterface $token)
|
||||
{
|
||||
if (!$request->hasSession() || !$request->hasPreviousSession()) {
|
||||
if (!$this->sessionStrategy || !$request->hasSession() || !$request->hasPreviousSession()) {
|
||||
return;
|
||||
}
|
||||
$request->getSession()->migrate(true);
|
||||
|
||||
$this->sessionStrategy->onAuthentication($request, $token);
|
||||
}
|
||||
}
|
||||
|
@ -202,6 +202,7 @@ class UsernamePasswordJsonAuthenticationListener implements ListenerInterface
|
||||
if (!$this->sessionStrategy || !$request->hasSession() || !$request->hasPreviousSession()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->sessionStrategy->onAuthentication($request, $token);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user