bug #16108 [Security] #15764. Use SessionAuthenticationStrategy on RememberMe login (s12v)

This PR was submitted for the 2.8 branch but it was merged into the 2.7 branch instead (closes #16108).

Discussion
----------

[Security] #15764. Use SessionAuthenticationStrategy on RememberMe login

Regenerate session ID with default session strategy.

| Q             | A
| ------------- | ---
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #15764
| License       | MIT
| Doc PR        | -

Commits
-------

795c8b3 [Security] Use SessionAuthenticationStrategy on RememberMe login
This commit is contained in:
Fabien Potencier 2015-10-16 13:32:26 +02:00
commit 3510e0a2de
3 changed files with 89 additions and 10 deletions

View File

@ -25,6 +25,7 @@
<argument type="service" id="logger" on-invalid="null" /> <argument type="service" id="logger" on-invalid="null" />
<argument type="service" id="event_dispatcher" on-invalid="null"/> <argument type="service" id="event_dispatcher" on-invalid="null"/>
<argument /> <!-- Catch exception flag set in RememberMeFactory --> <argument /> <!-- Catch exception flag set in RememberMeFactory -->
<argument type="service" id="security.authentication.session_strategy" />
</service> </service>
<service id="security.authentication.provider.rememberme" class="%security.authentication.provider.rememberme.class%" abstract="true" public="false"> <service id="security.authentication.provider.rememberme" class="%security.authentication.provider.rememberme.class%" abstract="true" public="false">

View File

@ -20,6 +20,7 @@ use Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent; use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
use Symfony\Component\Security\Http\SecurityEvents; use Symfony\Component\Security\Http\SecurityEvents;
use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface;
/** /**
* RememberMeListener implements authentication capabilities via a cookie. * RememberMeListener implements authentication capabilities via a cookie.
@ -34,18 +35,20 @@ class RememberMeListener implements ListenerInterface
private $logger; private $logger;
private $dispatcher; private $dispatcher;
private $catchExceptions = true; private $catchExceptions = true;
private $sessionStrategy;
/** /**
* Constructor. * Constructor.
* *
* @param TokenStorageInterface $tokenStorage * @param TokenStorageInterface $tokenStorage
* @param RememberMeServicesInterface $rememberMeServices * @param RememberMeServicesInterface $rememberMeServices
* @param AuthenticationManagerInterface $authenticationManager * @param AuthenticationManagerInterface $authenticationManager
* @param LoggerInterface $logger * @param LoggerInterface $logger
* @param EventDispatcherInterface $dispatcher * @param EventDispatcherInterface $dispatcher
* @param bool $catchExceptions * @param bool $catchExceptions
* @param SessionAuthenticationStrategyInterface $sessionStrategy
*/ */
public function __construct(TokenStorageInterface $tokenStorage, RememberMeServicesInterface $rememberMeServices, AuthenticationManagerInterface $authenticationManager, LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null, $catchExceptions = true) public function __construct(TokenStorageInterface $tokenStorage, RememberMeServicesInterface $rememberMeServices, AuthenticationManagerInterface $authenticationManager, LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null, $catchExceptions = true, SessionAuthenticationStrategyInterface $sessionStrategy = null)
{ {
$this->tokenStorage = $tokenStorage; $this->tokenStorage = $tokenStorage;
$this->rememberMeServices = $rememberMeServices; $this->rememberMeServices = $rememberMeServices;
@ -53,6 +56,7 @@ class RememberMeListener implements ListenerInterface
$this->logger = $logger; $this->logger = $logger;
$this->dispatcher = $dispatcher; $this->dispatcher = $dispatcher;
$this->catchExceptions = $catchExceptions; $this->catchExceptions = $catchExceptions;
$this->sessionStrategy = $sessionStrategy;
} }
/** /**
@ -73,6 +77,9 @@ class RememberMeListener implements ListenerInterface
try { try {
$token = $this->authenticationManager->authenticate($token); $token = $this->authenticationManager->authenticate($token);
if (null !== $this->sessionStrategy && $request->hasSession() && $request->getSession()->isStarted()) {
$this->sessionStrategy->onAuthentication($request, $token);
}
$this->tokenStorage->setToken($token); $this->tokenStorage->setToken($token);
if (null !== $this->dispatcher) { if (null !== $this->dispatcher) {

View File

@ -181,6 +181,71 @@ class RememberMeListenerTest extends \PHPUnit_Framework_TestCase
$listener->handle($event); $listener->handle($event);
} }
public function testSessionStrategy()
{
list($listener, $tokenStorage, $service, $manager, , $dispatcher, $sessionStrategy) = $this->getListener(false, true, true);
$tokenStorage
->expects($this->once())
->method('getToken')
->will($this->returnValue(null))
;
$token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
$service
->expects($this->once())
->method('autoLogin')
->will($this->returnValue($token))
;
$tokenStorage
->expects($this->once())
->method('setToken')
->with($this->equalTo($token))
;
$manager
->expects($this->once())
->method('authenticate')
->will($this->returnValue($token))
;
$session = $this->getMock('\Symfony\Component\HttpFoundation\Session\SessionInterface');
$session
->expects($this->once())
->method('isStarted')
->will($this->returnValue(true))
;
$request = $this->getMock('\Symfony\Component\HttpFoundation\Request');
$request
->expects($this->once())
->method('hasSession')
->will($this->returnValue(true))
;
$request
->expects($this->once())
->method('getSession')
->will($this->returnValue($session))
;
$event = $this->getGetResponseEvent();
$event
->expects($this->once())
->method('getRequest')
->will($this->returnValue($request))
;
$sessionStrategy
->expects($this->once())
->method('onAuthentication')
->will($this->returnValue(null))
;
$listener->handle($event);
}
public function testOnCoreSecurityInteractiveLoginEventIsDispatchedIfDispatcherIsPresent() public function testOnCoreSecurityInteractiveLoginEventIsDispatchedIfDispatcherIsPresent()
{ {
list($listener, $tokenStorage, $service, $manager, , $dispatcher) = $this->getListener(true); list($listener, $tokenStorage, $service, $manager, , $dispatcher) = $this->getListener(true);
@ -240,7 +305,7 @@ class RememberMeListenerTest extends \PHPUnit_Framework_TestCase
return $this->getMock('Symfony\Component\HttpKernel\Event\FilterResponseEvent', array(), array(), '', false); return $this->getMock('Symfony\Component\HttpKernel\Event\FilterResponseEvent', array(), array(), '', false);
} }
protected function getListener($withDispatcher = false, $catchExceptions = true) protected function getListener($withDispatcher = false, $catchExceptions = true, $withSessionStrategy = false)
{ {
$listener = new RememberMeListener( $listener = new RememberMeListener(
$tokenStorage = $this->getTokenStorage(), $tokenStorage = $this->getTokenStorage(),
@ -248,10 +313,11 @@ class RememberMeListenerTest extends \PHPUnit_Framework_TestCase
$manager = $this->getManager(), $manager = $this->getManager(),
$logger = $this->getLogger(), $logger = $this->getLogger(),
$dispatcher = ($withDispatcher ? $this->getDispatcher() : null), $dispatcher = ($withDispatcher ? $this->getDispatcher() : null),
$catchExceptions $catchExceptions,
$sessionStrategy = ($withSessionStrategy ? $this->getSessionStrategy() : null)
); );
return array($listener, $tokenStorage, $service, $manager, $logger, $dispatcher); return array($listener, $tokenStorage, $service, $manager, $logger, $dispatcher, $sessionStrategy);
} }
protected function getLogger() protected function getLogger()
@ -278,4 +344,9 @@ class RememberMeListenerTest extends \PHPUnit_Framework_TestCase
{ {
return $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); return $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface');
} }
private function getSessionStrategy()
{
return $this->getMock('\Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface');
}
} }