Track session usage when setting the token

This commit is contained in:
Wouter de Jong 2020-04-03 15:39:47 +02:00
parent 15edfd39d4
commit 8d96dbd08b
9 changed files with 86 additions and 4 deletions

View File

@ -23,7 +23,7 @@ class AppCustomAuthenticator extends AbstractGuardAuthenticator
{
public function supports(Request $request)
{
return true;
return '/manual_login' !== $request->getPathInfo() && '/profile' !== $request->getPathInfo();
}
public function getCredentials(Request $request)

View File

@ -0,0 +1,38 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\GuardedBundle;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Core\User\User;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Guard\GuardAuthenticatorHandler;
use Symfony\Component\Security\Guard\Token\PostAuthenticationGuardToken;
class AuthenticationController
{
public function manualLoginAction(GuardAuthenticatorHandler $guardAuthenticatorHandler, Request $request)
{
$guardAuthenticatorHandler->authenticateWithToken(new PostAuthenticationGuardToken(new User('Jane', 'test', ['ROLE_USER']), 'secure', ['ROLE_USER']), $request, 'secure');
return new Response('Logged in.');
}
public function profileAction(UserInterface $user = null)
{
if (null === $user) {
return new Response('Not logged in.');
}
return new Response('Username: '.$user->getUsername());
}
}

View File

@ -21,4 +21,14 @@ class GuardedTest extends AbstractWebTestCase
$this->assertSame(418, $client->getResponse()->getStatusCode());
}
public function testManualLogin()
{
$client = $this->createClient(['debug' => true, 'test_case' => 'Guarded', 'root_config' => 'config.yml']);
$client->request('GET', '/manual_login');
$client->request('GET', '/profile');
$this->assertSame('Username: Jane', $client->getResponse()->getContent());
}
}

View File

@ -10,8 +10,19 @@ framework:
services:
logger: { class: Psr\Log\NullLogger }
Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\GuardedBundle\AppCustomAuthenticator: ~
Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\GuardedBundle\AuthenticationController:
tags: [controller.service_arguments]
security:
encoders:
Symfony\Component\Security\Core\User\User: plaintext
providers:
in_memory:
memory:
users:
Jane: { password: test, roles: [ROLE_USER] }
firewalls:
secure:
pattern: ^/

View File

@ -3,3 +3,12 @@ main:
defaults:
_controller: Symfony\Bundle\FrameworkBundle\Controller\RedirectController::urlRedirectAction
path: /app
profile:
path: /profile
defaults:
_controller: Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\GuardedBundle\AuthenticationController::profileAction
manual_login:
path: /manual_login
defaults:
_controller: Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\GuardedBundle\AuthenticationController::manualLoginAction

View File

@ -49,6 +49,11 @@ class TokenStorage implements TokenStorageInterface, ResetInterface
@trigger_error(sprintf('Not implementing the "%s::getRoleNames()" method in "%s" is deprecated since Symfony 4.3.', TokenInterface::class, \get_class($token)), E_USER_DEPRECATED);
}
if ($token) {
// ensure any initializer is called
$this->getToken();
}
$this->initializer = null;
$this->token = $token;
}

View File

@ -52,6 +52,11 @@ final class UsageTrackingTokenStorage implements TokenStorageInterface, ServiceS
public function setToken(TokenInterface $token = null): void
{
$this->storage->setToken($token);
if ($token && $this->enableUsageTracking) {
// increments the internal session usage index
$this->sessionLocator->get('session')->getMetadataBag();
}
}
public function enableUsageTracking(): void

View File

@ -411,9 +411,9 @@ class ContextListenerTest extends TestCase
private function handleEventWithPreviousSession($userProviders, UserInterface $user = null, RememberMeServicesInterface $rememberMeServices = null)
{
$user = $user ?: new User('foo', 'bar');
$tokenUser = $user ?: new User('foo', 'bar');
$session = new Session(new MockArraySessionStorage());
$session->set('_security_context_key', serialize(new UsernamePasswordToken($user, '', 'context_key', ['ROLE_USER'])));
$session->set('_security_context_key', serialize(new UsernamePasswordToken($tokenUser, '', 'context_key', ['ROLE_USER'])));
$request = new Request();
$request->setSession($session);
@ -442,6 +442,10 @@ class ContextListenerTest extends TestCase
$listener(new RequestEvent($this->getMockBuilder(HttpKernelInterface::class)->getMock(), $request, HttpKernelInterface::MASTER_REQUEST));
if (null !== $usageIndex) {
if (null !== $user) {
++$usageIndex;
}
$this->assertSame($usageIndex, $session->getUsageIndex());
$tokenStorage->getToken();
$this->assertSame(1 + $usageIndex, $session->getUsageIndex());

View File

@ -17,7 +17,7 @@
],
"require": {
"php": "^7.1.3",
"symfony/security-core": "^4.4.7",
"symfony/security-core": "^4.4.8",
"symfony/http-foundation": "^3.4.40|^4.4.7|^5.0.7",
"symfony/http-kernel": "^4.4",
"symfony/property-access": "^3.4|^4.0|^5.0"