[Security] Rename UserInterface::getUsername() to getUserIdentifier()

This commit is contained in:
Wouter de Jong 2021-03-10 17:10:58 +01:00 committed by Robin Chalas
parent c469ea6fff
commit 8afd7a3765
116 changed files with 1000 additions and 486 deletions

View File

@ -9,6 +9,7 @@ Asset
DoctrineBridge
--------------
* Deprecate `UserLoaderInterface::loadUserByUsername()` in favor of `UserLoaderInterface::loadUserByIdentifier()
* Remove `UuidV*Generator` classes
DomCrawler
@ -178,6 +179,11 @@ Security
}
```
* Deprecate `UserInterface::getUsername()` in favor of `UserInterface::getUserIdentifier()`
* Deprecate `TokenInterface::getUsername()` in favor of `TokenInterface::getUserIdentifier()`
* Deprecate `UserProviderInterface::loadUserByUsername()` in favor of `UserProviderInterface::loadUserByIdentifier()`
* Deprecate `UsernameNotFoundException` in favor of `UserNotFoundException` and `getUsername()`/`setUsername()` in favor of `getUserIdentifier()`/`setUserIdentifier()`
* Deprecate `PersistentTokenInterface::getUsername()` in favor of `PersistentTokenInterface::getUserIdentifier()`
* Deprecate calling `PasswordUpgraderInterface::upgradePassword()` with a `UserInterface` instance that does not implement `PasswordAuthenticatedUserInterface`
* Deprecate calling methods `hashPassword()`, `isPasswordValid()` and `needsRehash()` on `UserPasswordHasherInterface` with a `UserInterface` instance that does not implement `PasswordAuthenticatedUserInterface`
* Deprecate all classes in the `Core\Encoder\` sub-namespace, use the `PasswordHasher` component instead

View File

@ -6,6 +6,11 @@ Asset
* Removed `RemoteJsonManifestVersionStrategy`, use `JsonManifestVersionStrategy` instead.
DoctrineBridge
--------------
* Remove `UserLoaderInterface::loadUserByUsername()` in favor of `UserLoaderInterface::loadUserByIdentifier()
Config
------
@ -262,6 +267,11 @@ Security
}
```
* Remove `UserInterface::getUsername()` in favor of `UserInterface::getUserIdentifier()`
* Remove `TokenInterface::getUsername()` in favor of `TokenInterface::getUserIdentifier()`
* Remove `UserProviderInterface::loadUserByUsername()` in favor of `UserProviderInterface::loadUserByIdentifier()`
* Remove `UsernameNotFoundException` in favor of `UserNotFoundException` and `getUsername()`/`setUsername()` in favor of `getUserIdentifier()`/`setUserIdentifier()`
* Remove `PersistentTokenInterface::getUsername()` in favor of `PersistentTokenInterface::getUserIdentifier()`
* Calling `PasswordUpgraderInterface::upgradePassword()` with a `UserInterface` instance that
does not implement `PasswordAuthenticatedUserInterface` now throws a `\TypeError`.
* Calling methods `hashPassword()`, `isPasswordValid()` and `needsRehash()` on `UserPasswordHasherInterface`

View File

@ -4,6 +4,7 @@ CHANGELOG
5.3
---
* Deprecate `UserLoaderInterface::loadUserByUsername()` in favor of `UserLoaderInterface::loadUserByIdentifier()
* Deprecate `DoctrineTestHelper` and `TestRepositoryFactory`
* [BC BREAK] Remove `UuidV*Generator` classes
* Add `UuidGenerator`

View File

@ -119,7 +119,8 @@ class DoctrineTokenProvider implements TokenProviderInterface
.' VALUES (:class, :username, :series, :value, :lastUsed)';
$paramValues = [
'class' => $token->getClass(),
'username' => $token->getUsername(),
// @deprecated since 5.3, change to $token->getUserIdentifier() in 6.0
'username' => method_exists($token, 'getUserIdentifier') ? $token->getUserIdentifier() : $token->getUsername(),
'series' => $token->getSeries(),
'value' => $token->getTokenValue(),
'lastUsed' => $token->getLastUsed(),

View File

@ -16,7 +16,7 @@ use Doctrine\Persistence\Mapping\ClassMetadata;
use Doctrine\Persistence\ObjectManager;
use Doctrine\Persistence\ObjectRepository;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\Exception\UserNotFoundException;
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
use Symfony\Component\Security\Core\User\PasswordUpgraderInterface;
use Symfony\Component\Security\Core\User\UserInterface;
@ -50,21 +50,35 @@ class EntityUserProvider implements UserProviderInterface, PasswordUpgraderInter
* {@inheritdoc}
*/
public function loadUserByUsername(string $username)
{
trigger_deprecation('symfony/doctrine-bridge', '5.3', 'Method "%s()" is deprecated, use loadUserByIdentifier() instead.', __METHOD__);
return $this->loadUserByIdentifier($username);
}
public function loadUserByIdentifier(string $identifier): UserInterface
{
$repository = $this->getRepository();
if (null !== $this->property) {
$user = $repository->findOneBy([$this->property => $username]);
$user = $repository->findOneBy([$this->property => $identifier]);
} else {
if (!$repository instanceof UserLoaderInterface) {
throw new \InvalidArgumentException(sprintf('You must either make the "%s" entity Doctrine Repository ("%s") implement "Symfony\Bridge\Doctrine\Security\User\UserLoaderInterface" or set the "property" option in the corresponding entity provider configuration.', $this->classOrAlias, get_debug_type($repository)));
}
$user = $repository->loadUserByUsername($username);
// @deprecated since 5.3, change to $repository->loadUserByIdentifier() in 6.0
if (method_exists($repository, 'loadUserByIdentifier')) {
$user = $repository->loadUserByIdentifier($identifier);
} else {
trigger_deprecation('symfony/doctrine-bridge', '5.3', 'Not implementing method "loadUserByIdentifier()" in user loader "%s" is deprecated. This method will replace "loadUserByUsername()" in Symfony 6.0.', get_debug_type($repository));
$user = $repository->loadUserByUsername($identifier);
}
}
if (null === $user) {
$e = new UsernameNotFoundException(sprintf('User "%s" not found.', $username));
$e->setUsername($username);
$e = new UserNotFoundException(sprintf('User "%s" not found.', $identifier));
$e->setUserIdentifier($identifier);
throw $e;
}
@ -96,8 +110,8 @@ class EntityUserProvider implements UserProviderInterface, PasswordUpgraderInter
$refreshedUser = $repository->find($id);
if (null === $refreshedUser) {
$e = new UsernameNotFoundException('User with id '.json_encode($id).' not found.');
$e->setUsername(json_encode($id));
$e = new UserNotFoundException('User with id '.json_encode($id).' not found.');
$e->setUserIdentifier(json_encode($id));
throw $e;
}

View File

@ -22,16 +22,11 @@ use Symfony\Component\Security\Core\User\UserInterface;
*
* @see UserInterface
*
* @method UserInterface|null loadUserByIdentifier(string $identifier) loads the user for the given user identifier (e.g. username or email).
* This method must return null if the user is not found.
*
* @author Michal Trojanowski <michal@kmt-studio.pl>
*/
interface UserLoaderInterface
{
/**
* Loads the user for the given username.
*
* This method must return null if the user is not found.
*
* @return UserInterface|null
*/
public function loadUserByUsername(string $username);
}

View File

@ -37,4 +37,9 @@ class BaseUser
{
return $this->username;
}
public function getUserIdentifier(): string
{
return $this->username;
}
}

View File

@ -53,6 +53,11 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface
return $this->name;
}
public function getUserIdentifier(): string
{
return $this->name;
}
public function eraseCredentials()
{
}

View File

@ -21,7 +21,7 @@ use Symfony\Bridge\Doctrine\Security\User\EntityUserProvider;
use Symfony\Bridge\Doctrine\Security\User\UserLoaderInterface;
use Symfony\Bridge\Doctrine\Tests\DoctrineTestHelper;
use Symfony\Bridge\Doctrine\Tests\Fixtures\User;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\Exception\UserNotFoundException;
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
use Symfony\Component\Security\Core\User\PasswordUpgraderInterface;
use Symfony\Component\Security\Core\User\UserInterface;
@ -60,7 +60,7 @@ class EntityUserProviderTest extends TestCase
$provider = new EntityUserProvider($this->getManager($em), 'Symfony\Bridge\Doctrine\Tests\Fixtures\User', 'name');
$this->assertSame($user, $provider->loadUserByUsername('user1'));
$this->assertSame($user, $provider->loadUserByIdentifier('user1'));
}
public function testLoadUserByUsernameWithUserLoaderRepositoryAndWithoutProperty()
@ -70,7 +70,7 @@ class EntityUserProviderTest extends TestCase
$repository = $this->createMock(UserLoaderRepository::class);
$repository
->expects($this->once())
->method('loadUserByUsername')
->method('loadUserByIdentifier')
->with('user1')
->willReturn($user);
@ -82,7 +82,7 @@ class EntityUserProviderTest extends TestCase
->willReturn($repository);
$provider = new EntityUserProvider($this->getManager($em), 'Symfony\Bridge\Doctrine\Tests\Fixtures\User');
$this->assertSame($user, $provider->loadUserByUsername('user1'));
$this->assertSame($user, $provider->loadUserByIdentifier('user1'));
}
public function testLoadUserByUsernameWithNonUserLoaderRepositoryAndWithoutProperty()
@ -98,7 +98,7 @@ class EntityUserProviderTest extends TestCase
$em->flush();
$provider = new EntityUserProvider($this->getManager($em), 'Symfony\Bridge\Doctrine\Tests\Fixtures\User');
$provider->loadUserByUsername('user1');
$provider->loadUserByIdentifier('user1');
}
public function testRefreshUserRequiresId()
@ -126,7 +126,7 @@ class EntityUserProviderTest extends TestCase
$provider = new EntityUserProvider($this->getManager($em), 'Symfony\Bridge\Doctrine\Tests\Fixtures\User', 'name');
$user2 = new User(1, 2, 'user2');
$this->expectException(UsernameNotFoundException::class);
$this->expectException(UserNotFoundException::class);
$this->expectExceptionMessage('User with id {"id1":1,"id2":2} not found');
$provider->refreshUser($user2);
@ -153,7 +153,7 @@ class EntityUserProviderTest extends TestCase
{
$repository = $this->createMock(UserLoaderRepository::class);
$repository->expects($this->once())
->method('loadUserByUsername')
->method('loadUserByIdentifier')
->with('name')
->willReturn(
$this->createMock(UserInterface::class)
@ -164,7 +164,7 @@ class EntityUserProviderTest extends TestCase
'Symfony\Bridge\Doctrine\Tests\Fixtures\User'
);
$provider->loadUserByUsername('name');
$provider->loadUserByIdentifier('name');
}
public function testLoadUserByUserNameShouldDeclineInvalidInterface()
@ -177,7 +177,7 @@ class EntityUserProviderTest extends TestCase
'Symfony\Bridge\Doctrine\Tests\Fixtures\User'
);
$provider->loadUserByUsername('name');
$provider->loadUserByIdentifier('name');
}
public function testPasswordUpgrades()
@ -231,6 +231,7 @@ class EntityUserProviderTest extends TestCase
abstract class UserLoaderRepository implements ObjectRepository, UserLoaderInterface
{
abstract public function loadUserByIdentifier(string $identifier): ?UserInterface;
}
abstract class PasswordUpgraderRepository implements ObjectRepository, PasswordUpgraderInterface

View File

@ -42,10 +42,16 @@ abstract class AbstractTokenProcessor
if (null !== $token = $this->getToken()) {
$record['extra'][$this->getKey()] = [
'username' => $token->getUsername(),
'authenticated' => $token->isAuthenticated(),
'roles' => $token->getRoleNames(),
];
// @deprecated since 5.3, change to $token->getUserIdentifier() in 6.0
if (method_exists($token, 'getUserIdentifier')) {
$record['extra'][$this->getKey()]['username'] = $record['extra'][$this->getKey()]['user_identifier'] = $token->getUserIdentifier();
} else {
$record['extra'][$this->getKey()]['username'] = $token->getUsername();
}
}
return $record;

View File

@ -37,11 +37,15 @@ class SwitchUserTokenProcessorTest extends TestCase
$expected = [
'impersonator_token' => [
'username' => 'original_user',
'authenticated' => true,
'roles' => ['ROLE_SUPER_ADMIN'],
'username' => 'original_user',
],
];
$this->assertSame($expected, $record['extra']);
if (method_exists($originalToken, 'getUserIdentifier')) {
$expected['impersonator_token']['user_identifier'] = 'original_user';
}
$this->assertEquals($expected, $record['extra']);
}
}

View File

@ -23,8 +23,12 @@ use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
*/
class TokenProcessorTest extends TestCase
{
public function testProcessor()
public function testLegacyProcessor()
{
if (method_exists(UsernamePasswordToken::class, 'getUserIdentifier')) {
$this->markTestSkipped('This test requires symfony/security-core <5.3');
}
$token = new UsernamePasswordToken('user', 'password', 'provider', ['ROLE_USER']);
$tokenStorage = $this->createMock(TokenStorageInterface::class);
$tokenStorage->method('getToken')->willReturn($token);
@ -38,4 +42,24 @@ class TokenProcessorTest extends TestCase
$this->assertEquals($token->isAuthenticated(), $record['extra']['token']['authenticated']);
$this->assertEquals(['ROLE_USER'], $record['extra']['token']['roles']);
}
public function testProcessor()
{
if (!method_exists(UsernamePasswordToken::class, 'getUserIdentifier')) {
$this->markTestSkipped('This test requires symfony/security-core 5.3+');
}
$token = new UsernamePasswordToken('user', 'password', 'provider', ['ROLE_USER']);
$tokenStorage = $this->createMock(TokenStorageInterface::class);
$tokenStorage->method('getToken')->willReturn($token);
$processor = new TokenProcessor($tokenStorage);
$record = ['extra' => []];
$record = $processor($record);
$this->assertArrayHasKey('token', $record['extra']);
$this->assertEquals($token->getUserIdentifier(), $record['extra']['token']['user_identifier']);
$this->assertEquals($token->isAuthenticated(), $record['extra']['token']['authenticated']);
$this->assertEquals(['ROLE_USER'], $record['extra']['token']['roles']);
}
}

View File

@ -21,6 +21,6 @@ class SecurityController implements ContainerAwareInterface
public function profileAction()
{
return new Response('Welcome '.$this->container->get('security.token_storage')->getToken()->getUsername().'!');
return new Response('Welcome '.$this->container->get('security.token_storage')->getToken()->getUserIdentifier().'!');
}
}

View File

@ -97,7 +97,9 @@ class SecurityDataCollector extends DataCollector implements LateDataCollectorIn
$impersonatorUser = null;
if ($token instanceof SwitchUserToken) {
$impersonatorUser = $token->getOriginalToken()->getUsername();
$originalToken = $token->getOriginalToken();
// @deprecated since 5.3, change to $originalToken->getUserIdentifier() in 6.0
$impersonatorUser = method_exists($originalToken, 'getUserIdentifier') ? $originalToken->getUserIdentifier() : $originalToken->getUsername();
}
if (null !== $this->roleHierarchy) {
@ -126,7 +128,8 @@ class SecurityDataCollector extends DataCollector implements LateDataCollectorIn
'token' => $token,
'token_class' => $this->hasVarDumper ? new ClassStub(\get_class($token)) : \get_class($token),
'logout_url' => $logoutUrl,
'user' => $token->getUsername(),
// @deprecated since 5.3, change to $token->getUserIdentifier() in 6.0
'user' => method_exists($token, 'getUserIdentifier') ? $token->getUserIdentifier() : $token->getUsername(),
'roles' => $assignedRoles,
'inherited_roles' => array_unique($inheritedRoles),
'supports_role_hierarchy' => null !== $this->roleHierarchy,

View File

@ -48,8 +48,30 @@ class InMemoryFactory implements UserProviderFactoryInterface
->fixXmlConfig('user')
->children()
->arrayNode('users')
->useAttributeAsKey('name')
->useAttributeAsKey('identifier')
->normalizeKeys(false)
->beforeNormalization()
->always()
->then(function ($v) {
$deprecation = false;
foreach ($v as $i => $child) {
if (!isset($child['name'])) {
continue;
}
$deprecation = true;
$v[$i]['identifier'] = $child['name'];
unset($v[$i]['name']);
}
if ($deprecation) {
trigger_deprecation('symfony/security-bundle', '5.3', 'The "in_memory.user.name" option is deprecated, use "identifier" instead.');
}
return $v;
})
->end()
->prototype('array')
->children()
->scalarNode('password')->defaultNull()->end()

View File

@ -136,7 +136,8 @@
</xsd:complexType>
<xsd:complexType name="user">
<xsd:attribute name="name" type="xsd:string" use="required" />
<xsd:attribute name="identifier" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="password" type="xsd:string" />
<xsd:attribute name="roles" type="xsd:string" />
</xsd:complexType>

View File

@ -297,7 +297,7 @@ abstract class CompleteConfigurationTest extends TestCase
} elseif (3 === $i) {
$this->assertEquals('IS_AUTHENTICATED_ANONYMOUSLY', $attributes[0]);
$expression = $container->getDefinition((string) $attributes[1])->getArgument(0);
$this->assertEquals("token.getUsername() matches '/^admin/'", $expression);
$this->assertEquals("token.getUserIdentifier() matches '/^admin/'", $expression);
}
}
}

View File

@ -97,7 +97,7 @@ $container->loadFromExtension('security', [
'access_control' => [
['path' => '/blog/524', 'role' => 'ROLE_USER', 'requires_channel' => 'https', 'methods' => ['get', 'POST'], 'port' => 8000],
['path' => '/blog/.*', 'role' => 'IS_AUTHENTICATED_ANONYMOUSLY'],
['path' => '/blog/524', 'role' => 'IS_AUTHENTICATED_ANONYMOUSLY', 'allow_if' => "token.getUsername() matches '/^admin/'"],
['path' => '/blog/524', 'role' => 'IS_AUTHENTICATED_ANONYMOUSLY', 'allow_if' => "token.getUserIdentifier() matches '/^admin/'"],
],
'role_hierarchy' => [

View File

@ -97,7 +97,7 @@ $container->loadFromExtension('security', [
'access_control' => [
['path' => '/blog/524', 'role' => 'ROLE_USER', 'requires_channel' => 'https', 'methods' => ['get', 'POST'], 'port' => 8000],
['path' => '/blog/.*', 'role' => 'IS_AUTHENTICATED_ANONYMOUSLY'],
['path' => '/blog/524', 'role' => 'IS_AUTHENTICATED_ANONYMOUSLY', 'allow_if' => "token.getUsername() matches '/^admin/'"],
['path' => '/blog/524', 'role' => 'IS_AUTHENTICATED_ANONYMOUSLY', 'allow_if' => "token.getUserIdentifier() matches '/^admin/'"],
],
'role_hierarchy' => [

View File

@ -12,7 +12,7 @@
<provider name="default">
<memory>
<user name="foo" password="foo" roles="ROLE_USER" />
<user identifier="foo" password="foo" roles="ROLE_USER" />
</memory>
</provider>

View File

@ -10,7 +10,7 @@
<config>
<provider name="default">
<memory>
<user name="foo" password="foo" roles="ROLE_USER" />
<user identifier="foo" password="foo" roles="ROLE_USER" />
</memory>
</provider>

View File

@ -12,7 +12,7 @@
<provider name="default">
<memory>
<user name="foo" password="foo" roles="ROLE_USER" />
<user identifier="foo" password="foo" roles="ROLE_USER" />
</memory>
</provider>

View File

@ -12,7 +12,7 @@
<provider name="default">
<memory>
<user name="foo" password="foo" roles="ROLE_USER" />
<user identifier="foo" password="foo" roles="ROLE_USER" />
</memory>
</provider>

View File

@ -25,20 +25,20 @@
<provider name="default">
<memory>
<user name="foo" password="foo" roles="ROLE_USER" />
<user identifier="foo" password="foo" roles="ROLE_USER" />
</memory>
</provider>
<provider name="digest">
<memory>
<user name="foo" password="foo" roles="ROLE_USER, ROLE_ADMIN" />
<user identifier="foo" password="foo" roles="ROLE_USER, ROLE_ADMIN" />
</memory>
</provider>
<provider name="basic">
<memory>
<user name="foo" password="0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33" roles="ROLE_SUPER_ADMIN" />
<user name="bar" password="0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33" roles="ROLE_USER, ROLE_ADMIN" />
<user identifier="foo" password="0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33" roles="ROLE_SUPER_ADMIN" />
<user identifier="bar" password="0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33" roles="ROLE_USER, ROLE_ADMIN" />
</memory>
</provider>
@ -78,6 +78,6 @@
<rule path="/blog/524" role="ROLE_USER" requires-channel="https" methods="get,POST" port="8000" />
<rule role='IS_AUTHENTICATED_ANONYMOUSLY' path="/blog/.*" />
<rule role='IS_AUTHENTICATED_ANONYMOUSLY' allow-if="token.getUsername() matches '/^admin/'" path="/blog/524" />
<rule role='IS_AUTHENTICATED_ANONYMOUSLY' allow-if="token.getUserIdentifier() matches '/^admin/'" path="/blog/524" />
</config>
</srv:container>

View File

@ -25,20 +25,20 @@
<provider name="default">
<memory>
<user name="foo" password="foo" roles="ROLE_USER" />
<user identifier="foo" password="foo" roles="ROLE_USER" />
</memory>
</provider>
<provider name="digest">
<memory>
<user name="foo" password="foo" roles="ROLE_USER, ROLE_ADMIN" />
<user identifier="foo" password="foo" roles="ROLE_USER, ROLE_ADMIN" />
</memory>
</provider>
<provider name="basic">
<memory>
<user name="foo" password="0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33" roles="ROLE_SUPER_ADMIN" />
<user name="bar" password="0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33" roles="ROLE_USER, ROLE_ADMIN" />
<user identifier="foo" password="0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33" roles="ROLE_SUPER_ADMIN" />
<user identifier="bar" password="0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33" roles="ROLE_USER, ROLE_ADMIN" />
</memory>
</provider>
@ -78,6 +78,6 @@
<rule path="/blog/524" role="ROLE_USER" requires-channel="https" methods="get,POST" port="8000" />
<rule role='IS_AUTHENTICATED_ANONYMOUSLY' path="/blog/.*" />
<rule role='IS_AUTHENTICATED_ANONYMOUSLY' allow-if="token.getUsername() matches '/^admin/'" path="/blog/524" />
<rule role='IS_AUTHENTICATED_ANONYMOUSLY' allow-if="token.getUserIdentifier() matches '/^admin/'" path="/blog/524" />
</config>
</srv:container>

View File

@ -10,7 +10,7 @@
<config>
<provider name="default">
<memory>
<user name="foo" password="foo" roles="ROLE_USER" />
<user identifier="foo" password="foo" roles="ROLE_USER" />
</memory>
</provider>

View File

@ -84,4 +84,4 @@ security:
-
path: /blog/.*
role: IS_AUTHENTICATED_ANONYMOUSLY
- { path: /blog/524, role: IS_AUTHENTICATED_ANONYMOUSLY, allow_if: "token.getUsername() matches '/^admin/'" }
- { path: /blog/524, role: IS_AUTHENTICATED_ANONYMOUSLY, allow_if: "token.getUserIdentifier() matches '/^admin/'" }

View File

@ -84,4 +84,4 @@ security:
-
path: /blog/.*
role: IS_AUTHENTICATED_ANONYMOUSLY
- { path: /blog/524, role: IS_AUTHENTICATED_ANONYMOUSLY, allow_if: "token.getUsername() matches '/^admin/'" }
- { path: /blog/524, role: IS_AUTHENTICATED_ANONYMOUSLY, allow_if: "token.getUserIdentifier() matches '/^admin/'" }

View File

@ -19,6 +19,6 @@ class ProfileController extends AbstractController
{
$this->denyAccessUnlessGranted('ROLE_USER');
return $this->json(['email' => $this->getUser()->getUsername()]);
return $this->json(['email' => $this->getUser()->getUserIdentifier()]);
}
}

View File

@ -1,7 +1,7 @@
{% extends "base.html.twig" %}
{% block body %}
Hello {{ app.user.username }}!<br /><br />
Hello {{ app.user.userIdentifier }}!<br /><br />
You're browsing to path "{{ app.request.pathInfo }}".<br /><br />
<a href="{{ logout_path('default') }}">Log out</a>.
<a href="{{ logout_url('default') }}">Log out</a>.

View File

@ -1,7 +1,7 @@
{% extends "base.html.twig" %}
{% block body %}
Hello {{ user.username }}!<br /><br />
Hello {{ user.userIdentifier }}!<br /><br />
You're browsing to path "{{ app.request.pathInfo }}".
<a href="{{ logout_path('default') }}">Log out</a>.

View File

@ -33,6 +33,6 @@ class AuthenticationController
return new Response('Not logged in.');
}
return new Response('Username: '.$user->getUsername());
return new Response('Username: '.$user->getUserIdentifier());
}
}

View File

@ -21,6 +21,6 @@ class TestController
{
public function loginCheckAction(UserInterface $user)
{
return new JsonResponse(['message' => sprintf('Welcome @%s!', $user->getUsername())]);
return new JsonResponse(['message' => sprintf('Welcome @%s!', $user->getUserIdentifier())]);
}
}

View File

@ -21,6 +21,6 @@ class JsonAuthenticationSuccessHandler implements AuthenticationSuccessHandlerIn
{
public function onAuthenticationSuccess(Request $request, TokenInterface $token): Response
{
return new JsonResponse(['message' => sprintf('Good game @%s!', $token->getUsername())]);
return new JsonResponse(['message' => sprintf('Good game @%s!', $token->getUserIdentifier())]);
}
}

View File

@ -11,6 +11,6 @@ class TestCustomLoginLinkSuccessHandler implements AuthenticationSuccessHandlerI
{
public function onAuthenticationSuccess(Request $request, TokenInterface $token)
{
return new JsonResponse(['message' => sprintf('Welcome %s!', $token->getUsername())]);
return new JsonResponse(['message' => sprintf('Welcome %s!', $token->getUserIdentifier())]);
}
}

View File

@ -4,7 +4,7 @@ namespace Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\SecuredPageBundl
use Symfony\Bundle\SecurityBundle\Tests\Functional\UserWithoutEquatable;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\Exception\UserNotFoundException;
use Symfony\Component\Security\Core\User\InMemoryUser;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
@ -16,7 +16,7 @@ class ArrayUserProvider implements UserProviderInterface
public function addUser(UserInterface $user)
{
$this->users[$user->getUsername()] = $user;
$this->users[$user->getUserIdentifier()] = $user;
}
public function setUser($username, UserInterface $user)
@ -31,11 +31,16 @@ class ArrayUserProvider implements UserProviderInterface
public function loadUserByUsername($username)
{
$user = $this->getUser($username);
return $this->loadUserByIdentifier($username);
}
public function loadUserByIdentifier(string $identifier): UserInterface
{
$user = $this->getUser($identifier);
if (null === $user) {
$e = new UsernameNotFoundException(sprintf('User "%s" not found.', $username));
$e->setUsername($username);
$e = new UserNotFoundException(sprintf('User "%s" not found.', $identifier));
$e->setUsername($identifier);
throw $e;
}
@ -49,10 +54,10 @@ class ArrayUserProvider implements UserProviderInterface
throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', get_debug_type($user)));
}
$storedUser = $this->getUser($user->getUsername());
$storedUser = $this->getUser($user->getUserIdentifier());
$class = \get_class($storedUser);
return new $class($storedUser->getUsername(), $storedUser->getPassword(), $storedUser->getRoles(), $storedUser->isEnabled());
return new $class($storedUser->getUserIdentifier(), $storedUser->getPassword(), $storedUser->getRoles(), $storedUser->isEnabled());
}
public function supportsClass($class)

View File

@ -51,7 +51,7 @@ class RememberMeFooController
{
public function __invoke(UserInterface $user)
{
return new Response($user->getUsername());
return new Response($user->getUserIdentifier());
}
}
@ -66,7 +66,12 @@ class RememberMeUserProvider implements UserProviderInterface
public function loadUserByUsername($username)
{
return $this->inner->loadUserByUsername($username);
return $this->loadUserByIdentifier($username);
}
public function loadUserByIdentifier(string $identifier): UserInterface
{
return $this->inner->loadUserByIdentifier($identifier);
}
public function refreshUser(UserInterface $user)

View File

@ -28,7 +28,7 @@ class LoginLinkAuthenticationTest extends AbstractWebTestCase
$this->markTestSkipped('Login link auth requires symfony/security-http:^5.2');
}
$client = $this->createClient(['test_case' => 'LoginLink', 'root_config' => 'config.yml']);
$client = $this->createClient(['test_case' => 'LoginLink', 'root_config' => 'config.yml', 'debug' => true]);
// we need an active request that is under the firewall to use the linker
$request = Request::create('/get-login-link');

View File

@ -106,7 +106,7 @@ final class UserWithoutEquatable implements UserInterface, PasswordAuthenticated
public function __toString()
{
return $this->getUsername();
return $this->getUserIdentifier();
}
/**
@ -141,6 +141,11 @@ final class UserWithoutEquatable implements UserInterface, PasswordAuthenticated
return $this->username;
}
public function getUserIdentifier()
{
return $this->username;
}
/**
* {@inheritdoc}
*/

View File

@ -83,7 +83,8 @@ class CheckLdapCredentialsListener implements EventSubscriberInterface
} else {
throw new LogicException('Using the "query_string" config without using a "search_dn" and a "search_password" is not supported.');
}
$username = $ldap->escape($user->getUsername(), '', LdapInterface::ESCAPE_FILTER);
// @deprecated since 5.3, change to $user->getUserIdentifier() in 6.0
$username = $ldap->escape(method_exists($user, 'getUserIdentifier') ? $user->getUserIdentifier() : $user->getUsername(), '', LdapInterface::ESCAPE_FILTER);
$query = str_replace('{username}', $username, $ldapBadge->getQueryString());
$result = $ldap->query($ldapBadge->getDnString(), $query)->execute();
if (1 !== $result->count()) {
@ -92,7 +93,8 @@ class CheckLdapCredentialsListener implements EventSubscriberInterface
$dn = $result[0]->getDn();
} else {
$username = $ldap->escape($user->getUsername(), '', LdapInterface::ESCAPE_DN);
// @deprecated since 5.3, change to $user->getUserIdentifier() in 6.0
$username = $ldap->escape(method_exists($user, 'getUserIdentifier') ? $user->getUserIdentifier() : $user->getUsername(), '', LdapInterface::ESCAPE_DN);
$dn = str_replace('{username}', $username, $ldapBadge->getDnString());
}

View File

@ -75,6 +75,13 @@ class LdapUser implements UserInterface, PasswordAuthenticatedUserInterface, Equ
* {@inheritdoc}
*/
public function getUsername(): string
{
trigger_deprecation('symfony/security-core', '5.3', 'Method "%s()" is deprecated and will be removed in 6.0, use getUserIdentifier() instead.', __METHOD__);
return $this->username;
}
public function getUserIdentifier(): string
{
return $this->username;
}

View File

@ -17,7 +17,7 @@ use Symfony\Component\Ldap\Exception\ExceptionInterface;
use Symfony\Component\Ldap\LdapInterface;
use Symfony\Component\Security\Core\Exception\InvalidArgumentException;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\Exception\UserNotFoundException;
use Symfony\Component\Security\Core\User\PasswordUpgraderInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
@ -48,7 +48,7 @@ class LdapUserProvider implements UserProviderInterface, PasswordUpgraderInterfa
}
if (null === $filter) {
$filter = '({uid_key}={username})';
$filter = '({uid_key}={user_identifier})';
}
$this->ldap = $ldap;
@ -66,15 +66,22 @@ class LdapUserProvider implements UserProviderInterface, PasswordUpgraderInterfa
* {@inheritdoc}
*/
public function loadUserByUsername(string $username)
{
trigger_deprecation('symfony/ldap', '5.3', 'Method "%s()" is deprecated, use loadUserByIdentifier() instead.', __METHOD__);
return $this->loadUserByIdentifier($username);
}
public function loadUserByIdentifier(string $identifier): UserInterface
{
try {
$this->ldap->bind($this->searchDn, $this->searchPassword);
$username = $this->ldap->escape($username, '', LdapInterface::ESCAPE_FILTER);
$query = str_replace('{username}', $username, $this->defaultSearch);
$identifier = $this->ldap->escape($identifier, '', LdapInterface::ESCAPE_FILTER);
$query = str_replace(['{username}', '{user_identifier}'], $identifier, $this->defaultSearch);
$search = $this->ldap->query($this->baseDn, $query);
} catch (ConnectionException $e) {
$e = new UsernameNotFoundException(sprintf('User "%s" not found.', $username), 0, $e);
$e->setUsername($username);
$e = new UserNotFoundException(sprintf('User "%s" not found.', $identifier), 0, $e);
$e->setUserIdentifier($identifier);
throw $e;
}
@ -83,15 +90,15 @@ class LdapUserProvider implements UserProviderInterface, PasswordUpgraderInterfa
$count = \count($entries);
if (!$count) {
$e = new UsernameNotFoundException(sprintf('User "%s" not found.', $username));
$e->setUsername($username);
$e = new UserNotFoundException(sprintf('User "%s" not found.', $identifier));
$e->setUserIdentifier($identifier);
throw $e;
}
if ($count > 1) {
$e = new UsernameNotFoundException('More than one user found.');
$e->setUsername($username);
$e = new UserNotFoundException('More than one user found.');
$e->setUserIdentifier($identifier);
throw $e;
}
@ -100,12 +107,12 @@ class LdapUserProvider implements UserProviderInterface, PasswordUpgraderInterfa
try {
if (null !== $this->uidKey) {
$username = $this->getAttributeValue($entry, $this->uidKey);
$identifier = $this->getAttributeValue($entry, $this->uidKey);
}
} catch (InvalidArgumentException $e) {
}
return $this->loadUser($username, $entry);
return $this->loadUser($identifier, $entry);
}
/**
@ -117,7 +124,7 @@ class LdapUserProvider implements UserProviderInterface, PasswordUpgraderInterfa
throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', get_debug_type($user)));
}
return new LdapUser($user->getEntry(), $user->getUsername(), $user->getPassword(), $user->getRoles(), $user->getExtraFields());
return new LdapUser($user->getEntry(), $user->getUserIdentifier(), $user->getPassword(), $user->getRoles(), $user->getExtraFields());
}
/**
@ -157,7 +164,7 @@ class LdapUserProvider implements UserProviderInterface, PasswordUpgraderInterfa
*
* @return UserInterface
*/
protected function loadUser(string $username, Entry $entry)
protected function loadUser(string $identifier, Entry $entry)
{
$password = null;
$extraFields = [];
@ -170,7 +177,7 @@ class LdapUserProvider implements UserProviderInterface, PasswordUpgraderInterfa
$extraFields[$field] = $this->getAttributeValue($entry, $field);
}
return new LdapUser($entry, $username, $password, $this->defaultRoles, $extraFields);
return new LdapUser($entry, $identifier, $password, $this->defaultRoles, $extraFields);
}
private function getAttributeValue(Entry $entry, string $attribute)

View File

@ -20,7 +20,7 @@ use Symfony\Component\Ldap\LdapInterface;
use Symfony\Component\Ldap\Security\LdapUser;
use Symfony\Component\Ldap\Security\LdapUserProvider;
use Symfony\Component\Security\Core\Exception\InvalidArgumentException;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\Exception\UserNotFoundException;
/**
* @requires extension ldap
@ -29,7 +29,7 @@ class LdapUserProviderTest extends TestCase
{
public function testLoadUserByUsernameFailsIfCantConnectToLdap()
{
$this->expectException(UsernameNotFoundException::class);
$this->expectException(UserNotFoundException::class);
$ldap = $this->createMock(LdapInterface::class);
$ldap
@ -39,12 +39,12 @@ class LdapUserProviderTest extends TestCase
;
$provider = new LdapUserProvider($ldap, 'ou=MyBusiness,dc=symfony,dc=com');
$provider->loadUserByUsername('foo');
$provider->loadUserByIdentifier('foo');
}
public function testLoadUserByUsernameFailsIfNoLdapEntries()
{
$this->expectException(UsernameNotFoundException::class);
$this->expectException(UserNotFoundException::class);
$result = $this->createMock(CollectionInterface::class);
$query = $this->createMock(QueryInterface::class);
@ -71,12 +71,12 @@ class LdapUserProviderTest extends TestCase
;
$provider = new LdapUserProvider($ldap, 'ou=MyBusiness,dc=symfony,dc=com');
$provider->loadUserByUsername('foo');
$provider->loadUserByIdentifier('foo');
}
public function testLoadUserByUsernameFailsIfMoreThanOneLdapEntry()
{
$this->expectException(UsernameNotFoundException::class);
$this->expectException(UserNotFoundException::class);
$result = $this->createMock(CollectionInterface::class);
$query = $this->createMock(QueryInterface::class);
@ -103,7 +103,7 @@ class LdapUserProviderTest extends TestCase
;
$provider = new LdapUserProvider($ldap, 'ou=MyBusiness,dc=symfony,dc=com');
$provider->loadUserByUsername('foo');
$provider->loadUserByIdentifier('foo');
}
public function testLoadUserByUsernameFailsIfMoreThanOneLdapPasswordsInEntry()
@ -144,7 +144,7 @@ class LdapUserProviderTest extends TestCase
;
$provider = new LdapUserProvider($ldap, 'ou=MyBusiness,dc=symfony,dc=com', null, null, [], 'sAMAccountName', '({uid_key}={username})', 'userpassword');
$this->assertInstanceOf(LdapUser::class, $provider->loadUserByUsername('foo'));
$this->assertInstanceOf(LdapUser::class, $provider->loadUserByIdentifier('foo'));
}
public function testLoadUserByUsernameShouldNotFailIfEntryHasNoUidKeyAttribute()
@ -180,7 +180,7 @@ class LdapUserProviderTest extends TestCase
;
$provider = new LdapUserProvider($ldap, 'ou=MyBusiness,dc=symfony,dc=com', null, null, [], 'sAMAccountName', '({uid_key}={username})');
$this->assertInstanceOf(LdapUser::class, $provider->loadUserByUsername('foo'));
$this->assertInstanceOf(LdapUser::class, $provider->loadUserByIdentifier('foo'));
}
public function testLoadUserByUsernameFailsIfEntryHasNoPasswordAttribute()
@ -218,7 +218,7 @@ class LdapUserProviderTest extends TestCase
;
$provider = new LdapUserProvider($ldap, 'ou=MyBusiness,dc=symfony,dc=com', null, null, [], 'sAMAccountName', '({uid_key}={username})', 'userpassword');
$this->assertInstanceOf(LdapUser::class, $provider->loadUserByUsername('foo'));
$this->assertInstanceOf(LdapUser::class, $provider->loadUserByIdentifier('foo'));
}
public function testLoadUserByUsernameIsSuccessfulWithoutPasswordAttribute()
@ -254,7 +254,7 @@ class LdapUserProviderTest extends TestCase
;
$provider = new LdapUserProvider($ldap, 'ou=MyBusiness,dc=symfony,dc=com');
$this->assertInstanceOf(LdapUser::class, $provider->loadUserByUsername('foo'));
$this->assertInstanceOf(LdapUser::class, $provider->loadUserByIdentifier('foo'));
}
public function testLoadUserByUsernameIsSuccessfulWithoutPasswordAttributeAndWrongCase()
@ -290,7 +290,7 @@ class LdapUserProviderTest extends TestCase
;
$provider = new LdapUserProvider($ldap, 'ou=MyBusiness,dc=symfony,dc=com');
$this->assertSame('foo', $provider->loadUserByUsername('Foo')->getUsername());
$this->assertSame('foo', $provider->loadUserByIdentifier('Foo')->getUserIdentifier());
}
public function testLoadUserByUsernameIsSuccessfulWithPasswordAttribute()
@ -330,7 +330,7 @@ class LdapUserProviderTest extends TestCase
;
$provider = new LdapUserProvider($ldap, 'ou=MyBusiness,dc=symfony,dc=com', null, null, [], 'sAMAccountName', '({uid_key}={username})', 'userpassword', ['email']);
$this->assertInstanceOf(LdapUser::class, $provider->loadUserByUsername('foo'));
$this->assertInstanceOf(LdapUser::class, $provider->loadUserByIdentifier('foo'));
}
public function testRefreshUserShouldReturnUserWithSameProperties()

View File

@ -196,6 +196,10 @@ class SomeUser implements UserInterface
{
}
public function getUserIdentifier(): string
{
}
public function eraseCredentials()
{
}

View File

@ -4,6 +4,11 @@ CHANGELOG
5.3
---
* Deprecate `PersistentTokenInterface::getUsername()` in favor of `PersistentTokenInterface::getUserIdentifier()`
* Deprecate `UsernameNotFoundException` in favor of `UserNotFoundException` and `getUsername()`/`setUsername()` in favor of `getUserIdentifier()`/`setUserIdentifier()`
* Deprecate `UserProviderInterface::loadUserByUsername()` in favor of `UserProviderInterface::loadUserByIdentifier()`
* Deprecate `TokenInterface::getUsername()` in favor of `TokenInterface::getUserIdentifier()`
* Deprecate `UserInterface::getUsername()` in favor of `getUserIdentifier()`
* Add `PassportInterface:getBadges()`, implemented by `PassportTrait`
* [BC BREAK] Remove method `checkIfCompletelyResolved()` from `PassportInterface`, checking that passport badges are
resolved is up to `AuthenticatorManager`

View File

@ -21,6 +21,7 @@ use Symfony\Component\Security\Core\Exception\AccountStatusException;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
use Symfony\Component\Security\Core\Exception\ProviderNotFoundException;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
// Help opcache.preload discover always-needed symbols
@ -105,6 +106,11 @@ class AuthenticationProviderManager implements AuthenticationManagerInterface
$this->eventDispatcher->dispatch(new AuthenticationSuccessEvent($result), AuthenticationEvents::AUTHENTICATION_SUCCESS);
}
// @deprecated since 5.3
if ($user = $result->getUser() instanceof UserInterface && !method_exists($result->getUser(), 'getUserIdentifier')) {
trigger_deprecation('symfony/security-core', '5.3', 'Not implementing method "getUserIdentifier(): string" in user class "%s" is deprecated. This method will replace "getUsername()" in Symfony 6.0.', get_debug_type($result->getUser()));
}
return $result;
}

View File

@ -16,7 +16,7 @@ use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationServiceException;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\Exception\UserNotFoundException;
use Symfony\Component\Security\Core\User\LegacyPasswordAuthenticatedUserInterface;
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
use Symfony\Component\Security\Core\User\PasswordUpgraderInterface;
@ -108,7 +108,7 @@ class DaoAuthenticationProvider extends UserAuthenticationProvider
/**
* {@inheritdoc}
*/
protected function retrieveUser(string $username, UsernamePasswordToken $token)
protected function retrieveUser(string $userIdentifier, UsernamePasswordToken $token)
{
$user = $token->getUser();
if ($user instanceof UserInterface) {
@ -116,15 +116,22 @@ class DaoAuthenticationProvider extends UserAuthenticationProvider
}
try {
$user = $this->userProvider->loadUserByUsername($username);
// @deprecated since 5.3, change to $this->userProvider->loadUserByIdentifier() in 6.0
if (method_exists($this->userProvider, 'loadUserByIdentifier')) {
$user = $this->userProvider->loadUserByIdentifier($userIdentifier);
} else {
trigger_deprecation('symfony/security-core', '5.3', 'Not implementing method "loadUserByIdentifier()" in user provider "%s" is deprecated. This method will replace "loadUserByUsername()" in Symfony 6.0.', get_debug_type($this->userProvider));
$user = $this->userProvider->loadUserByUsername($userIdentifier);
}
if (!$user instanceof UserInterface) {
throw new AuthenticationServiceException('The user provider must return a UserInterface object.');
}
return $user;
} catch (UsernameNotFoundException $e) {
$e->setUsername($username);
} catch (UserNotFoundException $e) {
$e->setUserIdentifier($userIdentifier);
throw $e;
} catch (\Exception $e) {
$e = new AuthenticationServiceException($e->getMessage(), 0, $e);

View File

@ -16,7 +16,7 @@ use Symfony\Component\Ldap\LdapInterface;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
use Symfony\Component\Security\Core\Exception\LogicException;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\Exception\UserNotFoundException;
use Symfony\Component\Security\Core\User\UserCheckerInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
@ -38,7 +38,7 @@ class LdapBindAuthenticationProvider extends UserAuthenticationProvider
private $searchDn;
private $searchPassword;
public function __construct(UserProviderInterface $userProvider, UserCheckerInterface $userChecker, string $providerKey, LdapInterface $ldap, string $dnString = '{username}', bool $hideUserNotFoundExceptions = true, string $searchDn = '', string $searchPassword = '')
public function __construct(UserProviderInterface $userProvider, UserCheckerInterface $userChecker, string $providerKey, LdapInterface $ldap, string $dnString = '{user_identifier}', bool $hideUserNotFoundExceptions = true, string $searchDn = '', string $searchPassword = '')
{
parent::__construct($userChecker, $providerKey, $hideUserNotFoundExceptions);
@ -50,7 +50,7 @@ class LdapBindAuthenticationProvider extends UserAuthenticationProvider
}
/**
* Set a query string to use in order to find a DN for the username.
* Set a query string to use in order to find a DN for the user identifier.
*/
public function setQueryString(string $queryString)
{
@ -60,13 +60,20 @@ class LdapBindAuthenticationProvider extends UserAuthenticationProvider
/**
* {@inheritdoc}
*/
protected function retrieveUser(string $username, UsernamePasswordToken $token)
protected function retrieveUser(string $userIdentifier, UsernamePasswordToken $token)
{
if (AuthenticationProviderInterface::USERNAME_NONE_PROVIDED === $username) {
throw new UsernameNotFoundException('Username can not be null.');
if (AuthenticationProviderInterface::USERNAME_NONE_PROVIDED === $userIdentifier) {
throw new UserNotFoundException('User identifier can not be null.');
}
return $this->userProvider->loadUserByUsername($username);
// @deprecated since 5.3, change to $this->userProvider->loadUserByIdentifier() in 6.0
if (method_exists($this->userProvider, 'loadUserByIdentifier')) {
return $this->userProvider->loadUserByIdentifier($userIdentifier);
} else {
trigger_deprecation('symfony/security-core', '5.3', 'Not implementing method "loadUserByIdentifier()" in user provider "%s" is deprecated. This method will replace "loadUserByUsername()" in Symfony 6.0.', get_debug_type($this->userProvider));
return $this->userProvider->loadUserByUsername($userIdentifier);
}
}
/**
@ -74,7 +81,8 @@ class LdapBindAuthenticationProvider extends UserAuthenticationProvider
*/
protected function checkAuthentication(UserInterface $user, UsernamePasswordToken $token)
{
$username = $token->getUsername();
// @deprecated since 5.3, change to $token->getUserIdentifier() in 6.0
$userIdentifier = method_exists($token, 'getUserIdentifier') ? $token->getUserIdentifier() : $token->getUsername();
$password = $token->getCredentials();
if ('' === (string) $password) {
@ -88,8 +96,8 @@ class LdapBindAuthenticationProvider extends UserAuthenticationProvider
} else {
throw new LogicException('Using the "query_string" config without using a "search_dn" and a "search_password" is not supported.');
}
$username = $this->ldap->escape($username, '', LdapInterface::ESCAPE_FILTER);
$query = str_replace('{username}', $username, $this->queryString);
$userIdentifier = $this->ldap->escape($userIdentifier, '', LdapInterface::ESCAPE_FILTER);
$query = str_replace(['{username}', '{user_identifier}'], $userIdentifier, $this->queryString);
$result = $this->ldap->query($this->dnString, $query)->execute();
if (1 !== $result->count()) {
throw new BadCredentialsException('The presented username is invalid.');
@ -97,8 +105,8 @@ class LdapBindAuthenticationProvider extends UserAuthenticationProvider
$dn = $result[0]->getDn();
} else {
$username = $this->ldap->escape($username, '', LdapInterface::ESCAPE_DN);
$dn = str_replace('{username}', $username, $this->dnString);
$userIdentifier = $this->ldap->escape($userIdentifier, '', LdapInterface::ESCAPE_DN);
$dn = str_replace(['{username}', '{user_identifier}'], $userIdentifier, $this->dnString);
}
$this->ldap->bind($dn, $password);

View File

@ -24,7 +24,7 @@ use Symfony\Component\Security\Core\User\UserProviderInterface;
* This authentication provider will not perform any checks on authentication
* requests, as they should already be pre-authenticated. However, the
* UserProviderInterface implementation may still throw a
* UsernameNotFoundException, for example.
* UserNotFoundException, for example.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
@ -54,7 +54,15 @@ class PreAuthenticatedAuthenticationProvider implements AuthenticationProviderIn
throw new BadCredentialsException('No pre-authenticated principal found in request.');
}
$user = $this->userProvider->loadUserByUsername($user);
$userIdentifier = method_exists($token, 'getUserIdentifier') ? $token->getUserIdentifier() : $token->getUsername();
// @deprecated since 5.3, change to $this->userProvider->loadUserByIdentifier() in 6.0
if (method_exists($this->userProvider, 'loadUserByIdentifier')) {
$user = $this->userProvider->loadUserByIdentifier($userIdentifier);
} else {
trigger_deprecation('symfony/security-core', '5.3', 'Not implementing method "loadUserByIdentifier()" in user provider "%s" is deprecated. This method will replace "loadUserByUsername()" in Symfony 6.0.', get_debug_type($this->userProvider));
$user = $this->userProvider->loadUserByUsername($userIdentifier);
}
$this->userChecker->checkPostAuth($user);

View File

@ -51,7 +51,7 @@ class RememberMeAuthenticationProvider implements AuthenticationProviderInterfac
$user = $token->getUser();
if (!$token->getUser() instanceof UserInterface) {
if (!$user instanceof UserInterface) {
throw new LogicException(sprintf('Method "%s::getUser()" must return a "%s" instance, "%s" returned.', get_debug_type($token), UserInterface::class, get_debug_type($user)));
}

View File

@ -17,7 +17,7 @@ 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\UsernameNotFoundException;
use Symfony\Component\Security\Core\Exception\UserNotFoundException;
use Symfony\Component\Security\Core\User\UserCheckerInterface;
use Symfony\Component\Security\Core\User\UserInterface;
@ -55,18 +55,18 @@ abstract class UserAuthenticationProvider implements AuthenticationProviderInter
throw new AuthenticationException('The token is not supported by this authentication provider.');
}
$username = $token->getUsername();
$username = method_exists($token, 'getUserIdentifier') ? $token->getUserIdentifier() : $token->getUsername();
if ('' === $username || null === $username) {
$username = AuthenticationProviderInterface::USERNAME_NONE_PROVIDED;
}
try {
$user = $this->retrieveUser($username, $token);
} catch (UsernameNotFoundException $e) {
} catch (UserNotFoundException $e) {
if ($this->hideUserNotFoundExceptions) {
throw new BadCredentialsException('Bad credentials.', 0, $e);
}
$e->setUsername($username);
$e->setUserIdentifier($username);
throw $e;
}

View File

@ -45,7 +45,7 @@ class InMemoryTokenProvider implements TokenProviderInterface
$token = new PersistentToken(
$this->tokens[$series]->getClass(),
$this->tokens[$series]->getUsername(),
method_exists($this->tokens[$series], 'getUserIdentifier') ? $this->tokens[$series]->getUserIdentifier() : $this->tokens[$series]->getUsername(),
$series,
$tokenValue,
$lastUsed

View File

@ -19,18 +19,18 @@ namespace Symfony\Component\Security\Core\Authentication\RememberMe;
final class PersistentToken implements PersistentTokenInterface
{
private $class;
private $username;
private $userIdentifier;
private $series;
private $tokenValue;
private $lastUsed;
public function __construct(string $class, string $username, string $series, string $tokenValue, \DateTime $lastUsed)
public function __construct(string $class, string $userIdentifier, string $series, string $tokenValue, \DateTime $lastUsed)
{
if (empty($class)) {
throw new \InvalidArgumentException('$class must not be empty.');
}
if ('' === $username) {
throw new \InvalidArgumentException('$username must not be empty.');
if ('' === $userIdentifier) {
throw new \InvalidArgumentException('$userIdentifier must not be empty.');
}
if (empty($series)) {
throw new \InvalidArgumentException('$series must not be empty.');
@ -40,7 +40,7 @@ final class PersistentToken implements PersistentTokenInterface
}
$this->class = $class;
$this->username = $username;
$this->userIdentifier = $userIdentifier;
$this->series = $series;
$this->tokenValue = $tokenValue;
$this->lastUsed = $lastUsed;
@ -59,7 +59,14 @@ final class PersistentToken implements PersistentTokenInterface
*/
public function getUsername(): string
{
return $this->username;
trigger_deprecation('symfony/security-core', '5.3', 'Method "%s()" is deprecated, use getUserIdentifier() instead.', __METHOD__);
return $this->userIdentifier;
}
public function getUserIdentifier(): string
{
return $this->userIdentifier;
}
/**

View File

@ -15,6 +15,8 @@ namespace Symfony\Component\Security\Core\Authentication\RememberMe;
* Interface to be implemented by persistent token classes (such as
* Doctrine entities representing a remember-me token).
*
* @method string getUserIdentifier() returns the identifier used to authenticate (e.g. their e-mailaddress or username)
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
interface PersistentTokenInterface
@ -26,13 +28,6 @@ interface PersistentTokenInterface
*/
public function getClass();
/**
* Returns the username.
*
* @return string
*/
public function getUsername();
/**
* Returns the series.
*

View File

@ -51,10 +51,32 @@ abstract class AbstractToken implements TokenInterface
/**
* {@inheritdoc}
*/
public function getUsername()
public function getUsername(/* $legacy = true */)
{
if (1 === func_num_args() && false === func_get_arg(0)) {
return null;
}
trigger_deprecation('symfony/security-core', '5.3', 'Method "%s()" is deprecated, use getUserIdentifier() instead.', __METHOD__);
if ($this->user instanceof UserInterface) {
return $this->user->getUsername();
return method_exists($this->user, 'getUserIdentifier') ? $this->user->getUserIdentifier() : $this->user->getUsername();
}
return (string) $this->user;
}
public function getUserIdentifier(): string
{
// method returns "null" in non-legacy mode if not overriden
$username = $this->getUsername(false);
if (null !== $username) {
trigger_deprecation('symfony/security-core', '5.3', 'Method "%s::getUsername()" is deprecated, override "getUserIdentifier()" instead.', get_debug_type($this));
}
if ($this->user instanceof UserInterface) {
// @deprecated since 5.3, change to $user->getUserIdentifier() in 6.0
return method_exists($this->user, 'getUserIdentifier') ? $this->user->getUserIdentifier() : $this->user->getUsername();
}
return (string) $this->user;
@ -234,7 +256,7 @@ abstract class AbstractToken implements TokenInterface
$roles[] = $role;
}
return sprintf('%s(user="%s", authenticated=%s, roles="%s")', $class, $this->getUsername(), json_encode($this->authenticated), implode(', ', $roles));
return sprintf('%s(user="%s", authenticated=%s, roles="%s")', $class, $this->getUserIdentifier(), json_encode($this->authenticated), implode(', ', $roles));
}
/**
@ -283,7 +305,11 @@ abstract class AbstractToken implements TokenInterface
return true;
}
if ($this->user->getUsername() !== $user->getUsername()) {
// @deprecated since Symfony 5.3, drop getUsername() in 6.0
$userIdentifier = function ($user) {
return method_exists($user, 'getUserIdentifier') ? $user->getUserIdentifier() : $user->getUsername();
};
if ($userIdentifier($this->user) !== $userIdentifier($user)) {
return true;
}

View File

@ -42,6 +42,13 @@ class NullToken implements TokenInterface
}
public function getUsername()
{
trigger_deprecation('symfony/security-core', '5.3', 'Method "%s()" is deprecated, use getUserIdentifier() instead.', __METHOD__);
return '';
}
public function getUserIdentifier(): string
{
return '';
}

View File

@ -48,6 +48,11 @@ class TokenStorage implements TokenStorageInterface, ResetInterface
if ($token) {
// ensure any initializer is called
$this->getToken();
// @deprecated since 5.3
if (!method_exists($token, 'getUserIdentifier')) {
trigger_deprecation('symfony/security-core', '5.3', 'Not implementing method "getUserIdentifier(): string" in token class "%s" is deprecated. This method will replace "getUsername()" in Symfony 6.0.', get_debug_type($token));
}
}
$this->initializer = null;

View File

@ -16,6 +16,8 @@ use Symfony\Component\Security\Core\User\UserInterface;
/**
* TokenInterface is the interface for the user authentication information.
*
* @method string getUserIdentifier() returns the user identifier used during authentication (e.g. a user's e-mailaddress or username)
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
@ -65,13 +67,6 @@ interface TokenInterface extends \Serializable
*/
public function setUser($user);
/**
* Returns the username.
*
* @return string
*/
public function getUsername();
/**
* Returns whether the user is authenticated or not.
*

View File

@ -0,0 +1,96 @@
<?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\Component\Security\Core\Exception;
/**
* UserNotFoundException is thrown if a User cannot be found for the given identifier.
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Alexander <iam.asm89@gmail.com>
*/
class UserNotFoundException extends AuthenticationException
{
private $identifier;
/**
* {@inheritdoc}
*/
public function getMessageKey()
{
return 'Username could not be found.';
}
/**
* Get the user identifier (e.g. username or e-mailaddress).
*/
public function getUserIdentifier(): string
{
return $this->identifier;
}
/**
* @return string
*
* @deprecated
*/
public function getUsername()
{
trigger_deprecation('symfony/security-core', '5.3', 'Method "%s()" is deprecated, use getUserIdentifier() instead.', __METHOD__);
return $this->identifier;
}
/**
* Set the user identifier (e.g. username or e-mailaddress).
*/
public function setUserIdentifier(string $identifier): void
{
$this->identifier = $identifier;
}
/**
* @deprecated
*/
public function setUsername(string $username)
{
trigger_deprecation('symfony/security-core', '5.3', 'Method "%s()" is deprecated, use getUserIdentifier() instead.', __METHOD__);
$this->identifier = $username;
}
/**
* {@inheritdoc}
*/
public function getMessageData()
{
return ['{{ username }}' => $this->identifier, '{{ user_identifier }}' => $this->identifier];
}
/**
* {@inheritdoc}
*/
public function __serialize(): array
{
return [$this->identifier, parent::__serialize()];
}
/**
* {@inheritdoc}
*/
public function __unserialize(array $data): void
{
[$this->identifier, $parentData] = $data;
$parentData = \is_array($parentData) ? $parentData : unserialize($parentData);
parent::__unserialize($parentData);
}
}
class_alias(UserNotFoundException::class, UsernameNotFoundException::class);

View File

@ -11,65 +11,15 @@
namespace Symfony\Component\Security\Core\Exception;
/**
* UsernameNotFoundException is thrown if a User cannot be found by its username.
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Alexander <iam.asm89@gmail.com>
*/
class UsernameNotFoundException extends AuthenticationException
{
private $username;
trigger_deprecation('symfony/security-core', '5.3', 'The "%s" class is deprecated, use "%s" instead.', UsernameNotFoundException::class, UserNotFoundException::class);
/**
* {@inheritdoc}
*/
public function getMessageKey()
{
return 'Username could not be found.';
}
class_exists(UserNotFoundException::class);
if (false) {
/**
* Get the username.
*
* @return string
* @deprecated since Symfony 5.3 to be removed in 6.0, use UserNotFoundException instead.
*/
public function getUsername()
class UsernameNotFoundException extends AuthenticationException
{
return $this->username;
}
/**
* Set the username.
*/
public function setUsername(string $username)
{
$this->username = $username;
}
/**
* {@inheritdoc}
*/
public function getMessageData()
{
return ['{{ username }}' => $this->username];
}
/**
* {@inheritdoc}
*/
public function __serialize(): array
{
return [$this->username, parent::__serialize()];
}
/**
* {@inheritdoc}
*/
public function __unserialize(array $data): void
{
[$this->username, $parentData] = $data;
$parentData = \is_array($parentData) ? $parentData : unserialize($parentData);
parent::__unserialize($parentData);
}
}

View File

@ -23,6 +23,7 @@ use Symfony\Component\Security\Core\Event\AuthenticationSuccessEvent;
use Symfony\Component\Security\Core\Exception\AccountStatusException;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Exception\ProviderNotFoundException;
use Symfony\Component\Security\Core\User\InMemoryUser;
class AuthenticationProviderManagerTest extends TestCase
{
@ -90,9 +91,12 @@ class AuthenticationProviderManagerTest extends TestCase
public function testAuthenticateWhenOneReturnsAuthenticationExceptionButNotAll()
{
$expected = $this->createMock(TokenInterface::class);
$expected->expects($this->any())->method('getUser')->willReturn(new InMemoryUser('wouter', null));
$manager = new AuthenticationProviderManager([
$this->getAuthenticationProvider(true, null, AuthenticationException::class),
$this->getAuthenticationProvider(true, $expected = $this->createMock(TokenInterface::class)),
$this->getAuthenticationProvider(true, $expected),
]);
$token = $manager->authenticate($this->createMock(TokenInterface::class));
@ -106,8 +110,10 @@ class AuthenticationProviderManagerTest extends TestCase
->expects($this->never())
->method('supports')
;
$expected = $this->createMock(TokenInterface::class);
$expected->expects($this->any())->method('getUser')->willReturn(new InMemoryUser('wouter', null));
$manager = new AuthenticationProviderManager([
$this->getAuthenticationProvider(true, $expected = $this->createMock(TokenInterface::class)),
$this->getAuthenticationProvider(true, $expected),
$second,
]);

View File

@ -155,6 +155,10 @@ class FakeCustomToken implements TokenInterface
{
}
public function getUserIdentifier(): string
{
}
public function isAuthenticated(): bool
{
}

View File

@ -12,6 +12,7 @@
namespace Symfony\Component\Security\Core\Tests\Authentication\Provider;
use PHPUnit\Framework\TestCase;
use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait;
use Symfony\Component\PasswordHasher\Hasher\PasswordHasherFactoryInterface;
use Symfony\Component\PasswordHasher\Hasher\PlaintextPasswordHasher;
use Symfony\Component\PasswordHasher\PasswordHasherInterface;
@ -20,8 +21,9 @@ use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationServiceException;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\Exception\UserNotFoundException;
use Symfony\Component\Security\Core\User\InMemoryUser;
use Symfony\Component\Security\Core\User\InMemoryUserProvider;
use Symfony\Component\Security\Core\User\PasswordUpgraderInterface;
use Symfony\Component\Security\Core\User\UserCheckerInterface;
use Symfony\Component\Security\Core\User\UserInterface;
@ -29,13 +31,25 @@ use Symfony\Component\Security\Core\User\UserProviderInterface;
class DaoAuthenticationProviderTest extends TestCase
{
use ExpectDeprecationTrait;
/**
* @group legacy
*/
public function testRetrieveUserWhenProviderDoesNotReturnAnUserInterface()
{
$this->expectException(AuthenticationServiceException::class);
$provider = $this->getProvider('fabien');
$userProvider = $this->createMock(DaoAuthenticationProviderTest_UserProvider::class);
$userProvider->expects($this->once())
->method('loadUserByUsername')
->willReturn('fabien')
;
$provider = $this->getProvider(null, null, null, $userProvider);
$method = new \ReflectionMethod($provider, 'retrieveUser');
$method->setAccessible(true);
$this->expectDeprecation('Since symfony/security-core 5.3: Not implementing method "loadUserByIdentifier()" in user provider "'.get_debug_type($userProvider).'" is deprecated. This method will replace "loadUserByUsername()" in Symfony 6.0.');
$method->invoke($provider, 'fabien', $this->getSupportedToken());
}
@ -44,12 +58,8 @@ class DaoAuthenticationProviderTest extends TestCase
*/
public function testRetrieveUserWhenUsernameIsNotFoundWithLegacyEncoderFactory()
{
$this->expectException(UsernameNotFoundException::class);
$userProvider = $this->createMock(UserProviderInterface::class);
$userProvider->expects($this->once())
->method('loadUserByUsername')
->willThrowException(new UsernameNotFoundException())
;
$this->expectException(UserNotFoundException::class);
$userProvider = new InMemoryUserProvider();
$provider = new DaoAuthenticationProvider($userProvider, $this->createMock(UserCheckerInterface::class), 'key', $this->createMock(EncoderFactoryInterface::class));
$method = new \ReflectionMethod($provider, 'retrieveUser');
@ -60,12 +70,8 @@ class DaoAuthenticationProviderTest extends TestCase
public function testRetrieveUserWhenUsernameIsNotFound()
{
$this->expectException(UsernameNotFoundException::class);
$userProvider = $this->createMock(UserProviderInterface::class);
$userProvider->expects($this->once())
->method('loadUserByUsername')
->willThrowException(new UsernameNotFoundException())
;
$this->expectException(UserNotFoundException::class);
$userProvider = new InMemoryUserProvider();
$provider = new DaoAuthenticationProvider($userProvider, $this->createMock(UserCheckerInterface::class), 'key', $this->createMock(PasswordHasherFactoryInterface::class));
$method = new \ReflectionMethod($provider, 'retrieveUser');
@ -77,9 +83,9 @@ class DaoAuthenticationProviderTest extends TestCase
public function testRetrieveUserWhenAnExceptionOccurs()
{
$this->expectException(AuthenticationServiceException::class);
$userProvider = $this->createMock(UserProviderInterface::class);
$userProvider = $this->createMock(InMemoryUserProvider::class);
$userProvider->expects($this->once())
->method('loadUserByUsername')
->method('loadUserByIdentifier')
->willThrowException(new \RuntimeException())
;
@ -92,9 +98,9 @@ class DaoAuthenticationProviderTest extends TestCase
public function testRetrieveUserReturnsUserFromTokenOnReauthentication()
{
$userProvider = $this->createMock(UserProviderInterface::class);
$userProvider = $this->createMock(InMemoryUserProvider::class);
$userProvider->expects($this->never())
->method('loadUserByUsername')
->method('loadUserByIdentifier')
;
$user = new TestUser();
@ -114,19 +120,13 @@ class DaoAuthenticationProviderTest extends TestCase
public function testRetrieveUser()
{
$user = new TestUser();
$userProvider = $this->createMock(UserProviderInterface::class);
$userProvider->expects($this->once())
->method('loadUserByUsername')
->willReturn($user)
;
$userProvider = new InMemoryUserProvider(['fabien' => []]);
$provider = new DaoAuthenticationProvider($userProvider, $this->createMock(UserCheckerInterface::class), 'key', $this->createMock(PasswordHasherFactoryInterface::class));
$method = new \ReflectionMethod($provider, 'retrieveUser');
$method->setAccessible(true);
$this->assertSame($user, $method->invoke($provider, 'fabien', $this->getSupportedToken()));
$this->assertEquals('fabien', $method->invoke($provider, 'fabien', $this->getSupportedToken())->getUserIdentifier());
}
public function testCheckAuthenticationWhenCredentialsAreEmpty()
@ -323,14 +323,16 @@ class DaoAuthenticationProviderTest extends TestCase
return $mock;
}
protected function getProvider($user = null, $userChecker = null, $passwordHasher = null)
protected function getProvider($user = null, $userChecker = null, $passwordHasher = null, $userProvider = null)
{
$userProvider = $this->createMock(PasswordUpgraderProvider::class);
if (null !== $user) {
$userProvider->expects($this->once())
->method('loadUserByUsername')
->willReturn($user)
;
if (null === $userProvider) {
$userProvider = $this->createMock(PasswordUpgraderProvider::class);
if (null !== $user) {
$userProvider->expects($this->once())
->method('loadUserByIdentifier')
->willReturn($user)
;
}
}
if (null === $userChecker) {
@ -374,6 +376,11 @@ class TestUser implements UserInterface
return 'jane_doe';
}
public function getUserIdentifier(): string
{
return 'jane_doe';
}
public function eraseCredentials()
{
}
@ -381,4 +388,10 @@ class TestUser implements UserInterface
interface PasswordUpgraderProvider extends UserProviderInterface, PasswordUpgraderInterface
{
public function upgradePassword(UserInterface $user, string $newHashedPassword): void;
public function loadUserByIdentifier(string $identifier): UserInterface;
}
interface DaoAuthenticationProviderTest_UserProvider extends UserProviderInterface
{
public function loadUserByUsername($username);
}

View File

@ -21,6 +21,7 @@ use Symfony\Component\Security\Core\Authentication\Provider\LdapBindAuthenticati
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
use Symfony\Component\Security\Core\User\InMemoryUser;
use Symfony\Component\Security\Core\User\InMemoryUserProvider;
use Symfony\Component\Security\Core\User\UserCheckerInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
@ -81,10 +82,10 @@ class LdapBindAuthenticationProviderTest extends TestCase
public function testRetrieveUser()
{
$userProvider = $this->createMock(UserProviderInterface::class);
$userProvider = $this->createMock(InMemoryUserProvider::class);
$userProvider
->expects($this->once())
->method('loadUserByUsername')
->method('loadUserByIdentifier')
->with('foo')
;
$ldap = $this->createMock(LdapInterface::class);

View File

@ -18,6 +18,7 @@ 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\Core\Exception\LockedException;
use Symfony\Component\Security\Core\User\InMemoryUserProvider;
use Symfony\Component\Security\Core\User\UserCheckerInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
@ -120,10 +121,10 @@ class PreAuthenticatedAuthenticationProviderTest extends TestCase
protected function getProvider($user = null, $userChecker = null)
{
$userProvider = $this->createMock(UserProviderInterface::class);
$userProvider = $this->createMock(InMemoryUserProvider::class);
if (null !== $user) {
$userProvider->expects($this->once())
->method('loadUserByUsername')
->method('loadUserByIdentifier')
->willReturn($user)
;
}

View File

@ -21,7 +21,8 @@ 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\CredentialsExpiredException;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\Exception\UserNotFoundException;
use Symfony\Component\Security\Core\User\InMemoryUser;
use Symfony\Component\Security\Core\User\UserCheckerInterface;
use Symfony\Component\Security\Core\User\UserInterface;
@ -46,11 +47,11 @@ class UserAuthenticationProviderTest extends TestCase
public function testAuthenticateWhenUsernameIsNotFound()
{
$this->expectException(UsernameNotFoundException::class);
$this->expectException(UserNotFoundException::class);
$provider = $this->getProvider(false, false);
$provider->expects($this->once())
->method('retrieveUser')
->willThrowException(new UsernameNotFoundException())
->willThrowException(new UserNotFoundException())
;
$provider->authenticate($this->getSupportedToken());
@ -62,7 +63,7 @@ class UserAuthenticationProviderTest extends TestCase
$provider = $this->getProvider(false, true);
$provider->expects($this->once())
->method('retrieveUser')
->willThrowException(new UsernameNotFoundException())
->willThrowException(new UserNotFoundException())
;
$provider->authenticate($this->getSupportedToken());
@ -194,7 +195,7 @@ class UserAuthenticationProviderTest extends TestCase
;
$originalToken = $this->createMock(TokenInterface::class);
$token = new SwitchUserToken($this->createMock(UserInterface::class), 'foo', 'key', [], $originalToken);
$token = new SwitchUserToken(new InMemoryUser('wouter', null), 'foo', 'key', [], $originalToken);
$token->setAttributes(['foo' => 'bar']);
$authToken = $provider->authenticate($token);

View File

@ -12,19 +12,33 @@
namespace Symfony\Component\Security\Core\Tests\Authentication\RememberMe;
use PHPUnit\Framework\TestCase;
use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait;
use Symfony\Component\Security\Core\Authentication\RememberMe\PersistentToken;
class PersistentTokenTest extends TestCase
{
use ExpectDeprecationTrait;
public function testConstructor()
{
$lastUsed = new \DateTime();
$token = new PersistentToken('fooclass', 'fooname', 'fooseries', 'footokenvalue', $lastUsed);
$this->assertEquals('fooclass', $token->getClass());
$this->assertEquals('fooname', $token->getUsername());
$this->assertEquals('fooname', $token->getUserIdentifier());
$this->assertEquals('fooseries', $token->getSeries());
$this->assertEquals('footokenvalue', $token->getTokenValue());
$this->assertSame($lastUsed, $token->getLastUsed());
}
/**
* @group legacy
*/
public function testLegacyGetUsername()
{
$token = new PersistentToken('fooclass', 'fooname', 'fooseries', 'footokenvalue', new \DateTime());
$this->expectDeprecation('Since symfony/security-core 5.3: Method "Symfony\Component\Security\Core\Authentication\RememberMe\PersistentToken::getUsername()" is deprecated, use getUserIdentifier() instead.');
$this->assertEquals('fooname', $token->getUsername());
}
}

View File

@ -12,12 +12,19 @@
namespace Symfony\Component\Security\Core\Tests\Authentication\Token;
use PHPUnit\Framework\TestCase;
use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait;
use Symfony\Component\Security\Core\Authentication\Token\AbstractToken;
use Symfony\Component\Security\Core\User\InMemoryUser;
use Symfony\Component\Security\Core\User\UserInterface;
class AbstractTokenTest extends TestCase
{
public function testGetUsername()
use ExpectDeprecationTrait;
/**
* @group legacy
*/
public function testLegacyGetUsername()
{
$token = new ConcreteToken(['ROLE_FOO']);
$token->setUser('fabien');
@ -26,10 +33,43 @@ class AbstractTokenTest extends TestCase
$token->setUser(new TestUser('fabien'));
$this->assertEquals('fabien', $token->getUsername());
$user = $this->createMock(UserInterface::class);
$user->expects($this->once())->method('getUsername')->willReturn('fabien');
$token->setUser($user);
$legacyUser = new class implements UserInterface {
public function getUsername()
{
return 'fabien';
}
public function getRoles()
{}
public function getPassword()
{}
public function getSalt()
{}
public function eraseCredentials()
{}
};
$token->setUser($legacyUser);
$this->assertEquals('fabien', $token->getUsername());
$token->setUser($legacyUser);
$this->assertEquals('fabien', $token->getUserIdentifier());
}
public function testGetUserIdentifier()
{
$token = new ConcreteToken(['ROLE_FOO']);
$token->setUser('fabien');
$this->assertEquals('fabien', $token->getUserIdentifier());
$token->setUser(new TestUser('fabien'));
$this->assertEquals('fabien', $token->getUserIdentifier());
$user = new InMemoryUser('fabien', null);
$token->setUser($user);
$this->assertEquals('fabien', $token->getUserIdentifier());
}
public function testEraseCredentials()
@ -106,10 +146,8 @@ class AbstractTokenTest extends TestCase
public function getUsers()
{
$user = $this->createMock(UserInterface::class);
return [
[$user],
[new InMemoryUser('foo', null)],
[new TestUser('foo')],
['foo'],
];
@ -210,6 +248,11 @@ class SerializableUser implements UserInterface, \Serializable
return $this->name;
}
public function getUserIdentifier()
{
return $this->name;
}
public function getPassword()
{
return '***';

View File

@ -16,6 +16,7 @@ use Psr\Container\ContainerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\Security\Core\Authentication\Token\NullToken;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
use Symfony\Component\Security\Core\Authentication\Token\Storage\UsageTrackingTokenStorage;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
@ -46,7 +47,7 @@ class UsageTrackingTokenStorageTest extends TestCase
$trackingStorage = new UsageTrackingTokenStorage($tokenStorage, $sessionLocator);
$this->assertNull($trackingStorage->getToken());
$token = $this->createMock(TokenInterface::class);
$token = new NullToken();
$trackingStorage->setToken($token);
$this->assertSame($token, $trackingStorage->getToken());

View File

@ -26,7 +26,7 @@ class SwitchUserTokenTest extends TestCase
$unserializedToken = unserialize(serialize($token));
$this->assertInstanceOf(SwitchUserToken::class, $unserializedToken);
$this->assertSame('admin', $unserializedToken->getUsername());
$this->assertSame('admin', $unserializedToken->getUserIdentifier());
$this->assertSame('bar', $unserializedToken->getCredentials());
$this->assertSame('provider-key', $unserializedToken->getFirewallName());
$this->assertEquals(['ROLE_USER'], $unserializedToken->getRoleNames());
@ -35,7 +35,7 @@ class SwitchUserTokenTest extends TestCase
$unserializedOriginalToken = $unserializedToken->getOriginalToken();
$this->assertInstanceOf(UsernamePasswordToken::class, $unserializedOriginalToken);
$this->assertSame('user', $unserializedOriginalToken->getUsername());
$this->assertSame('user', $unserializedOriginalToken->getUserIdentifier());
$this->assertSame('foo', $unserializedOriginalToken->getCredentials());
$this->assertSame('provider-key', $unserializedOriginalToken->getFirewallName());
$this->assertEquals(['ROLE_ADMIN', 'ROLE_ALLOWED_TO_SWITCH'], $unserializedOriginalToken->getRoleNames());
@ -49,6 +49,11 @@ class SwitchUserTokenTest extends TestCase
return 'impersonated';
}
public function getUserIdentifier()
{
return 'impersonated';
}
public function getPassword()
{
return null;
@ -92,7 +97,7 @@ class SwitchUserTokenTest extends TestCase
self::assertInstanceOf(SwitchUserToken::class, $token);
self::assertInstanceOf(UsernamePasswordToken::class, $token->getOriginalToken());
self::assertSame('john', $token->getUsername());
self::assertSame('john', $token->getUserIdentifier());
self::assertSame(['foo' => 'bar'], $token->getCredentials());
self::assertSame('main', $token->getFirewallName());
self::assertEquals(['ROLE_USER'], $token->getRoleNames());

View File

@ -213,6 +213,10 @@ class SomeUser implements UserInterface
{
}
public function getUserIdentifier(): string
{
}
public function eraseCredentials()
{
}

View File

@ -0,0 +1,39 @@
<?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\Component\Security\Core\Tests\Exception;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Security\Core\Exception\UserNotFoundException;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
class UserNotFoundExceptionTest extends TestCase
{
public function testGetMessageData()
{
$exception = new UserNotFoundException('Username could not be found.');
$this->assertEquals(['{{ username }}' => null, '{{ user_identifier }}' => null], $exception->getMessageData());
$exception->setUserIdentifier('username');
$this->assertEquals(['{{ username }}' => 'username', '{{ user_identifier }}' => 'username'], $exception->getMessageData());
}
/**
* @group legacy
*/
public function testUsernameNotFoundException()
{
$exception = new UsernameNotFoundException();
$this->assertInstanceOf(UserNotFoundException::class, $exception);
$exception->setUsername('username');
$this->assertEquals('username', $exception->getUserIdentifier());
}
}

View File

@ -1,26 +0,0 @@
<?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\Component\Security\Core\Tests\Exception;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
class UsernameNotFoundExceptionTest extends TestCase
{
public function testGetMessageData()
{
$exception = new UsernameNotFoundException('Username could not be found.');
$this->assertEquals(['{{ username }}' => null], $exception->getMessageData());
$exception->setUsername('username');
$this->assertEquals(['{{ username }}' => 'username'], $exception->getMessageData());
}
}

View File

@ -13,9 +13,10 @@ namespace Symfony\Component\Security\Core\Tests\User;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\Exception\UserNotFoundException;
use Symfony\Component\Security\Core\User\ChainUserProvider;
use Symfony\Component\Security\Core\User\InMemoryUser;
use Symfony\Component\Security\Core\User\InMemoryUserProvider;
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
use Symfony\Component\Security\Core\User\PasswordUpgraderInterface;
use Symfony\Component\Security\Core\User\UserInterface;
@ -25,59 +26,59 @@ class ChainUserProviderTest extends TestCase
{
public function testLoadUserByUsername()
{
$provider1 = $this->createMock(UserProviderInterface::class);
$provider1 = $this->createMock(InMemoryUserProvider::class);
$provider1
->expects($this->once())
->method('loadUserByUsername')
->method('loadUserByIdentifier')
->with($this->equalTo('foo'))
->willThrowException(new UsernameNotFoundException('not found'))
->willThrowException(new UserNotFoundException('not found'))
;
$provider2 = $this->createMock(UserProviderInterface::class);
$provider2 = $this->createMock(InMemoryUserProvider::class);
$provider2
->expects($this->once())
->method('loadUserByUsername')
->method('loadUserByIdentifier')
->with($this->equalTo('foo'))
->willReturn($account = $this->createMock(UserInterface::class))
;
$provider = new ChainUserProvider([$provider1, $provider2]);
$this->assertSame($account, $provider->loadUserByUsername('foo'));
$this->assertSame($account, $provider->loadUserByIdentifier('foo'));
}
public function testLoadUserByUsernameThrowsUsernameNotFoundException()
public function testLoadUserByUsernameThrowsUserNotFoundException()
{
$this->expectException(UsernameNotFoundException::class);
$provider1 = $this->createMock(UserProviderInterface::class);
$this->expectException(UserNotFoundException::class);
$provider1 = $this->createMock(InMemoryUserProvider::class);
$provider1
->expects($this->once())
->method('loadUserByUsername')
->method('loadUserByIdentifier')
->with($this->equalTo('foo'))
->willThrowException(new UsernameNotFoundException('not found'))
->willThrowException(new UserNotFoundException('not found'))
;
$provider2 = $this->createMock(UserProviderInterface::class);
$provider2 = $this->createMock(InMemoryUserProvider::class);
$provider2
->expects($this->once())
->method('loadUserByUsername')
->method('loadUserByIdentifier')
->with($this->equalTo('foo'))
->willThrowException(new UsernameNotFoundException('not found'))
->willThrowException(new UserNotFoundException('not found'))
;
$provider = new ChainUserProvider([$provider1, $provider2]);
$provider->loadUserByUsername('foo');
$provider->loadUserByIdentifier('foo');
}
public function testRefreshUser()
{
$provider1 = $this->createMock(UserProviderInterface::class);
$provider1 = $this->createMock(InMemoryUserProvider::class);
$provider1
->expects($this->once())
->method('supportsClass')
->willReturn(false)
;
$provider2 = $this->createMock(UserProviderInterface::class);
$provider2 = $this->createMock(InMemoryUserProvider::class);
$provider2
->expects($this->once())
->method('supportsClass')
@ -90,7 +91,7 @@ class ChainUserProviderTest extends TestCase
->willThrowException(new UnsupportedUserException('unsupported'))
;
$provider3 = $this->createMock(UserProviderInterface::class);
$provider3 = $this->createMock(InMemoryUserProvider::class);
$provider3
->expects($this->once())
->method('supportsClass')
@ -109,7 +110,7 @@ class ChainUserProviderTest extends TestCase
public function testRefreshUserAgain()
{
$provider1 = $this->createMock(UserProviderInterface::class);
$provider1 = $this->createMock(InMemoryUserProvider::class);
$provider1
->expects($this->once())
->method('supportsClass')
@ -119,10 +120,10 @@ class ChainUserProviderTest extends TestCase
$provider1
->expects($this->once())
->method('refreshUser')
->willThrowException(new UsernameNotFoundException('not found'))
->willThrowException(new UserNotFoundException('not found'))
;
$provider2 = $this->createMock(UserProviderInterface::class);
$provider2 = $this->createMock(InMemoryUserProvider::class);
$provider2
->expects($this->once())
->method('supportsClass')
@ -142,7 +143,7 @@ class ChainUserProviderTest extends TestCase
public function testRefreshUserThrowsUnsupportedUserException()
{
$this->expectException(UnsupportedUserException::class);
$provider1 = $this->createMock(UserProviderInterface::class);
$provider1 = $this->createMock(InMemoryUserProvider::class);
$provider1
->expects($this->once())
->method('supportsClass')
@ -155,7 +156,7 @@ class ChainUserProviderTest extends TestCase
->willThrowException(new UnsupportedUserException('unsupported'))
;
$provider2 = $this->createMock(UserProviderInterface::class);
$provider2 = $this->createMock(InMemoryUserProvider::class);
$provider2
->expects($this->once())
->method('supportsClass')
@ -174,7 +175,7 @@ class ChainUserProviderTest extends TestCase
public function testSupportsClass()
{
$provider1 = $this->createMock(UserProviderInterface::class);
$provider1 = $this->createMock(InMemoryUserProvider::class);
$provider1
->expects($this->once())
->method('supportsClass')
@ -182,7 +183,7 @@ class ChainUserProviderTest extends TestCase
->willReturn(false)
;
$provider2 = $this->createMock(UserProviderInterface::class);
$provider2 = $this->createMock(InMemoryUserProvider::class);
$provider2
->expects($this->once())
->method('supportsClass')
@ -196,7 +197,7 @@ class ChainUserProviderTest extends TestCase
public function testSupportsClassWhenNotSupported()
{
$provider1 = $this->createMock(UserProviderInterface::class);
$provider1 = $this->createMock(InMemoryUserProvider::class);
$provider1
->expects($this->once())
->method('supportsClass')
@ -204,7 +205,7 @@ class ChainUserProviderTest extends TestCase
->willReturn(false)
;
$provider2 = $this->createMock(UserProviderInterface::class);
$provider2 = $this->createMock(InMemoryUserProvider::class);
$provider2
->expects($this->once())
->method('supportsClass')
@ -218,7 +219,7 @@ class ChainUserProviderTest extends TestCase
public function testAcceptsTraversable()
{
$provider1 = $this->createMock(UserProviderInterface::class);
$provider1 = $this->createMock(InMemoryUserProvider::class);
$provider1
->expects($this->once())
->method('supportsClass')
@ -231,7 +232,7 @@ class ChainUserProviderTest extends TestCase
->willThrowException(new UnsupportedUserException('unsupported'))
;
$provider2 = $this->createMock(UserProviderInterface::class);
$provider2 = $this->createMock(InMemoryUserProvider::class);
$provider2
->expects($this->once())
->method('supportsClass')

View File

@ -13,7 +13,7 @@ namespace Symfony\Component\Security\Core\Tests\User;
use PHPUnit\Framework\TestCase;
use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\Exception\UserNotFoundException;
use Symfony\Component\Security\Core\User\InMemoryUser;
use Symfony\Component\Security\Core\User\InMemoryUserProvider;
use Symfony\Component\Security\Core\User\User;
@ -26,7 +26,7 @@ class InMemoryUserProviderTest extends TestCase
{
$provider = $this->createProvider();
$user = $provider->loadUserByUsername('fabien');
$user = $provider->loadUserByIdentifier('fabien');
$this->assertEquals('foo', $user->getPassword());
$this->assertEquals(['ROLE_USER'], $user->getRoles());
$this->assertFalse($user->isEnabled());
@ -76,7 +76,7 @@ class InMemoryUserProviderTest extends TestCase
$provider = new InMemoryUserProvider();
$provider->createUser(new InMemoryUser('fabien', 'foo'));
$user = $provider->loadUserByUsername('fabien');
$user = $provider->loadUserByIdentifier('fabien');
$this->assertEquals('foo', $user->getPassword());
}
@ -90,8 +90,8 @@ class InMemoryUserProviderTest extends TestCase
public function testLoadUserByUsernameDoesNotExist()
{
$this->expectException(UsernameNotFoundException::class);
$this->expectException(UserNotFoundException::class);
$provider = new InMemoryUserProvider();
$provider->loadUserByUsername('fabien');
$provider->loadUserByIdentifier('fabien');
}
}

View File

@ -12,12 +12,15 @@
namespace Symfony\Component\Security\Core\Tests\User;
use PHPUnit\Framework\TestCase;
use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait;
use Symfony\Component\Security\Core\User\EquatableInterface;
use Symfony\Component\Security\Core\User\InMemoryUser;
use Symfony\Component\Security\Core\User\UserInterface;
class InMemoryUserTest extends TestCase
{
use ExpectDeprecationTrait;
public function testConstructorException()
{
$this->expectException(\InvalidArgumentException::class);
@ -39,12 +42,23 @@ class InMemoryUserTest extends TestCase
$this->assertEquals('superpass', $user->getPassword());
}
/**
* @group legacy
*/
public function testGetUsername()
{
$user = new InMemoryUser('fabien', 'superpass');
$this->expectDeprecation('Since symfony/security-core 5.3: Method "Symfony\Component\Security\Core\User\User::getUsername()" is deprecated, use getUserIdentifier() instead.');
$this->assertEquals('fabien', $user->getUsername());
}
public function testGetUserIdentifier()
{
$user = new InMemoryUser('fabien', 'superpass');
$this->assertEquals('fabien', $user->getUserIdentifier());
}
public function testGetSalt()
{
$user = new InMemoryUser('fabien', 'superpass');

View File

@ -12,6 +12,7 @@
namespace Symfony\Component\Security\Core\Tests\User;
use PHPUnit\Framework\TestCase;
use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait;
use Symfony\Component\Security\Core\User\EquatableInterface;
use Symfony\Component\Security\Core\User\User;
use Symfony\Component\Security\Core\User\UserInterface;
@ -21,6 +22,8 @@ use Symfony\Component\Security\Core\User\UserInterface;
*/
class UserTest extends TestCase
{
use ExpectDeprecationTrait;
public function testConstructorException()
{
$this->expectException(\InvalidArgumentException::class);
@ -42,12 +45,23 @@ class UserTest extends TestCase
$this->assertEquals('superpass', $user->getPassword());
}
/**
* @group legacy
*/
public function testGetUsername()
{
$user = new User('fabien', 'superpass');
$this->expectDeprecation('Since symfony/security-core 5.3: Method "Symfony\Component\Security\Core\User\User::getUsername()" is deprecated, use getUserIdentifier() instead.');
$this->assertEquals('fabien', $user->getUsername());
}
public function testGetUserIdentifier()
{
$user = new User('fabien', 'superpass');
$this->assertEquals('fabien', $user->getUserIdentifier());
}
public function testGetSalt()
{
$user = new User('fabien', 'superpass');

View File

@ -12,7 +12,7 @@
namespace Symfony\Component\Security\Core\User;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\Exception\UserNotFoundException;
/**
* Chain User Provider.
@ -50,17 +50,31 @@ class ChainUserProvider implements UserProviderInterface, PasswordUpgraderInterf
* {@inheritdoc}
*/
public function loadUserByUsername(string $username)
{
trigger_deprecation('symfony/security-core', '5.3', 'Method "%s()" is deprecated, use loadUserByIdentifier() instead.', __METHOD__);
return $this->loadUserByIdentifier($username);
}
public function loadUserByIdentifier(string $userIdentifier): UserInterface
{
foreach ($this->providers as $provider) {
try {
return $provider->loadUserByUsername($username);
} catch (UsernameNotFoundException $e) {
// @deprecated since 5.3, change to $provider->loadUserByIdentifier() in 6.0
if (!method_exists($provider, 'loadUserByIdentifier')) {
trigger_deprecation('symfony/security-core', '5.3', 'Not implementing method "loadUserByIdentifier()" in user provider "%s" is deprecated. This method will replace "loadUserByUsername()" in Symfony 6.0.', \get_debug_type($provider));
return $provider->loadUserByUsername($userIdentifier);
}
return $provider->loadUserByIdentifier($userIdentifier);
} catch (UserNotFoundException $e) {
// try next one
}
}
$ex = new UsernameNotFoundException(sprintf('There is no user with name "%s".', $username));
$ex->setUsername($username);
$ex = new UserNotFoundException(sprintf('There is no user with identifier "%s".', $userIdentifier));
$ex->setUserIdentifier($userIdentifier);
throw $ex;
}
@ -80,15 +94,17 @@ class ChainUserProvider implements UserProviderInterface, PasswordUpgraderInterf
return $provider->refreshUser($user);
} catch (UnsupportedUserException $e) {
// try next one
} catch (UsernameNotFoundException $e) {
} catch (UserNotFoundException $e) {
$supportedUserFound = true;
// try next one
}
}
if ($supportedUserFound) {
$e = new UsernameNotFoundException(sprintf('There is no user with name "%s".', $user->getUsername()));
$e->setUsername($user->getUsername());
// @deprecated since 5.3, change to $user->getUserIdentifier() in 6.0
$username = method_exists($user, 'getUserIdentifier') ? $user->getUserIdentifier() : $user->getUsername();
$e = new UserNotFoundException(sprintf('There is no user with name "%s".', $username));
$e->setUserIdentifier($username);
throw $e;
} else {
throw new UnsupportedUserException(sprintf('There is no user provider for user "%s". Shouldn\'t the "supportsClass()" method of your user provider return true for this classname?', get_debug_type($user)));

View File

@ -12,7 +12,7 @@
namespace Symfony\Component\Security\Core\User;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\Exception\UserNotFoundException;
/**
* InMemoryUserProvider is a simple non persistent user provider.
@ -51,11 +51,13 @@ class InMemoryUserProvider implements UserProviderInterface
*/
public function createUser(UserInterface $user)
{
if (isset($this->users[strtolower($user->getUsername())])) {
// @deprecated since 5.3, change to $user->getUserIdentifier() in 6.0
$userIdentifier = strtolower(method_exists($user, 'getUserIdentifier') ? $user->getUserIdentifier() : $user->getUsername());
if (isset($this->users[$userIdentifier])) {
throw new \LogicException('Another user with the same username already exists.');
}
$this->users[strtolower($user->getUsername())] = $user;
$this->users[$userIdentifier] = $user;
}
/**
@ -63,9 +65,17 @@ class InMemoryUserProvider implements UserProviderInterface
*/
public function loadUserByUsername(string $username)
{
$user = $this->getUser($username);
trigger_deprecation('symfony/security-core', '5.3', 'Method "%s()" is deprecated, use loadUserByIdentifier() instead.', __METHOD__);
return new InMemoryUser($user->getUsername(), $user->getPassword(), $user->getRoles(), $user->isEnabled());
return $this->loadUserByIdentifier($username);
}
public function loadUserByIdentifier(string $identifier): UserInterface
{
$user = $this->getUser($identifier);
// @deprecated since 5.3, change to $user->getUserIdentifier() in 6.0
return new InMemoryUser(method_exists($user, 'getUserIdentifier') ? $user->getUserIdentifier() : $user->getUsername(), $user->getPassword(), $user->getRoles(), $user->isEnabled());
}
/**
@ -77,7 +87,9 @@ class InMemoryUserProvider implements UserProviderInterface
throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', get_debug_type($user)));
}
$storedUser = $this->getUser($user->getUsername());
// @deprecated since 5.3, change to $user->getUserIdentifier() in 6.0
$storedUser = $this->getUser(method_exists($user, 'getUserIdentifier') ? $user->getUserIdentifier() : $user->getUsername());
$userIdentifier = method_exists($storedUser, 'getUserIdentifier') ? $storedUser->getUserIdentifier() : $storedUser->getUsername();
// @deprecated since Symfony 5.3
if (User::class === \get_class($user)) {
@ -91,10 +103,10 @@ class InMemoryUserProvider implements UserProviderInterface
$accountNonLocked = $storedUser->isAccountNonLocked();
}
return new User($storedUser->getUsername(), $storedUser->getPassword(), $storedUser->getRoles(), $storedUser->isEnabled(), $accountNonExpired, $credentialsNonExpired, $accountNonLocked);
return new User($userIdentifier, $storedUser->getPassword(), $storedUser->getRoles(), $storedUser->isEnabled(), $accountNonExpired, $credentialsNonExpired, $accountNonLocked);
}
return new InMemoryUser($storedUser->getUsername(), $storedUser->getPassword(), $storedUser->getRoles(), $storedUser->isEnabled());
return new InMemoryUser($userIdentifier, $storedUser->getPassword(), $storedUser->getRoles(), $storedUser->isEnabled());
}
/**
@ -113,13 +125,13 @@ class InMemoryUserProvider implements UserProviderInterface
/**
* Returns the user by given username.
*
* @throws UsernameNotFoundException if user whose given username does not exist
* @throws UserNotFoundException if user whose given username does not exist
*/
private function getUser(string $username)/*: InMemoryUser */
{
if (!isset($this->users[strtolower($username)])) {
$ex = new UsernameNotFoundException(sprintf('Username "%s" does not exist.', $username));
$ex->setUsername($username);
$ex = new UserNotFoundException(sprintf('Username "%s" does not exist.', $username));
$ex->setUserIdentifier($username);
throw $ex;
}

View File

@ -37,6 +37,11 @@ class MissingUserProvider implements UserProviderInterface
throw new \BadMethodCallException();
}
public function loadUserByIdentifier(string $identifier): UserInterface
{
throw new \BadMethodCallException();
}
/**
* {@inheritdoc}
*/

View File

@ -53,7 +53,7 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface, Equatab
public function __toString(): string
{
return $this->getUsername();
return $this->getUserIdentifier();
}
/**
@ -84,6 +84,16 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface, Equatab
* {@inheritdoc}
*/
public function getUsername(): string
{
trigger_deprecation('symfony/security-core', '5.3', 'Method "%s()" is deprecated, use getUserIdentifier() instead.', __METHOD__);
return $this->username;
}
/**
* Returns the identifier for this user (e.g. its username or e-mailaddress).
*/
public function getUserIdentifier(): string
{
return $this->username;
}
@ -184,7 +194,7 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface, Equatab
return false;
}
if ($this->getUsername() !== $user->getUsername()) {
if ($this->getUserIdentifier() !== $user->getUserIdentifier()) {
return false;
}

View File

@ -26,6 +26,8 @@ namespace Symfony\Component\Security\Core\User;
*
* @see UserProviderInterface
*
* @method string getUserIdentifier() returns the identifier for this user (e.g. its username or e-mailaddress)
*
* @author Fabien Potencier <fabien@symfony.com>
*/
interface UserInterface
@ -69,13 +71,6 @@ interface UserInterface
*/
public function getSalt();
/**
* Returns the username used to authenticate the user.
*
* @return string The username
*/
public function getUsername();
/**
* Removes sensitive data from the user.
*

View File

@ -12,16 +12,16 @@
namespace Symfony\Component\Security\Core\User;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\Exception\UserNotFoundException;
/**
* Represents a class that loads UserInterface objects from some source for the authentication system.
*
* In a typical authentication configuration, a username (i.e. some unique
* user identifier) credential enters the system (via form login, or any
* method). The user provider that is configured with that authentication
* method is asked to load the UserInterface object for the given username
* (via loadUserByUsername) so that the rest of the process can continue.
* In a typical authentication configuration, a user identifier (e.g. a
* username or e-mailaddress) credential enters the system (via form login, or
* any method). The user provider that is configured with that authentication
* method is asked to load the UserInterface object for the given identifier (via
* loadUserByIdentifier) so that the rest of the process can continue.
*
* Internally, a user provider can load users from any source (databases,
* configuration, web service). This is totally independent of how the authentication
@ -29,22 +29,13 @@ use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
*
* @see UserInterface
*
* @method UserInterface loadUserByIdentifier(string $identifier) loads the user for the given user identifier (e.g. username or email).
* This method must throw UserNotFoundException if the user is not found.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
interface UserProviderInterface
{
/**
* Loads the user for the given username.
*
* This method must throw UsernameNotFoundException if the user is not
* found.
*
* @return UserInterface
*
* @throws UsernameNotFoundException if the user is not found
*/
public function loadUserByUsername(string $username);
/**
* Refreshes the user.
*
@ -55,8 +46,8 @@ interface UserProviderInterface
*
* @return UserInterface
*
* @throws UnsupportedUserException if the user is not supported
* @throws UsernameNotFoundException if the user is not found
* @throws UnsupportedUserException if the user is not supported
* @throws UserNotFoundException if the user is not found
*/
public function refreshUser(UserInterface $user);

View File

@ -15,7 +15,7 @@ use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\Exception\UserNotFoundException;
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
use Symfony\Component\Security\Core\User\PasswordUpgraderInterface;
use Symfony\Component\Security\Core\User\UserInterface;
@ -98,7 +98,7 @@ class GuardBridgeAuthenticator implements InteractiveAuthenticatorInterface, Aut
$user = $this->guard->getUser($credentials, $this->userProvider);
if (null === $user) {
throw new UsernameNotFoundException(sprintf('Null returned from "%s::getUser()".', get_debug_type($this->guard)));
throw new UserNotFoundException(sprintf('Null returned from "%s::getUser()".', get_debug_type($this->guard)));
}
if (!$user instanceof UserInterface) {

View File

@ -70,7 +70,7 @@ interface AuthenticatorInterface extends AuthenticationEntryPointInterface
* The *credentials* are the return value from getCredentials()
*
* You may throw an AuthenticationException if you wish. If you return
* null, then a UsernameNotFoundException is thrown for you.
* null, then a UserNotFoundException is thrown for you.
*
* @param mixed $credentials
*

View File

@ -18,7 +18,7 @@ use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Exception\AuthenticationExpiredException;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\Exception\UserNotFoundException;
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
use Symfony\Component\Security\Core\User\PasswordUpgraderInterface;
use Symfony\Component\Security\Core\User\UserCheckerInterface;
@ -112,8 +112,9 @@ class GuardAuthenticationProvider implements AuthenticationProviderInterface
$user = $guardAuthenticator->getUser($token->getCredentials(), $this->userProvider);
if (null === $user) {
$e = new UsernameNotFoundException(sprintf('Null returned from "%s::getUser()".', get_debug_type($guardAuthenticator)));
$e->setUsername($token->getUsername());
$e = new UserNotFoundException(sprintf('Null returned from "%s::getUser()".', get_debug_type($guardAuthenticator)));
// @deprecated since 5.3, change to $token->getUserIdentifier() in 6.0
$e->setUserIdentifier(method_exists($token, 'getUserIdentifier') ? $token->getUserIdentifier() : $token->getUsername());
throw $e;
}

View File

@ -15,7 +15,7 @@ use PHPUnit\Framework\TestCase;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\Exception\UserNotFoundException;
use Symfony\Component\Security\Core\User\InMemoryUser;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Guard\Authenticator\GuardBridgeAuthenticator;
@ -97,7 +97,7 @@ class GuardBridgeAuthenticatorTest extends TestCase
public function testAuthenticateNoUser()
{
$this->expectException(UsernameNotFoundException::class);
$this->expectException(UserNotFoundException::class);
$request = new Request();

View File

@ -70,7 +70,8 @@ class AuthenticatorManager implements AuthenticatorManagerInterface, UserAuthent
public function authenticateUser(UserInterface $user, AuthenticatorInterface $authenticator, Request $request, array $badges = []): ?Response
{
// create an authenticated token for the User
$token = $authenticator->createAuthenticatedToken($passport = new SelfValidatingPassport(new UserBadge($user->getUsername(), function () use ($user) { return $user; }), $badges), $this->firewallName);
// @deprecated since 5.3, change to $user->getUserIdentifier() in 6.0
$token = $authenticator->createAuthenticatedToken($passport = new SelfValidatingPassport(new UserBadge(method_exists($user, 'getUserIdentifier') ? $user->getUserIdentifier() : $user->getUsername(), function () use ($user) { return $user; }), $badges), $this->firewallName);
// announce the authenticated token
$token = $this->eventDispatcher->dispatch(new AuthenticationTokenCreatedEvent($token))->getAuthenticatedToken();
@ -215,6 +216,11 @@ class AuthenticatorManager implements AuthenticatorManagerInterface, UserAuthent
private function handleAuthenticationSuccess(TokenInterface $authenticatedToken, PassportInterface $passport, Request $request, AuthenticatorInterface $authenticator): ?Response
{
// @deprecated since 5.3
if (!method_exists($authenticatedToken->getUser(), 'getUserIdentifier')) {
trigger_deprecation('symfony/security-core', '5.3', 'Not implementing method "getUserIdentifier(): string" in user class "%s" is deprecated. This method will replace "getUsername()" in Symfony 6.0.', get_debug_type($authenticatedToken->getUser()));
}
$this->tokenStorage->setToken($authenticatedToken);
$response = $authenticator->onAuthenticationSuccess($request, $authenticatedToken, $this->firewallName);

View File

@ -87,9 +87,18 @@ abstract class AbstractPreAuthenticatedAuthenticator implements InteractiveAuthe
public function authenticate(Request $request): PassportInterface
{
return new SelfValidatingPassport(new UserBadge($request->attributes->get('_pre_authenticated_username'), function ($username) {
return $this->userProvider->loadUserByUsername($username);
}), [new PreAuthenticatedUserBadge()]);
// @deprecated since 5.3, change to $this->userProvider->loadUserByIdentifier() in 6.0
$method = 'loadUserByIdentifier';
if (!method_exists($this->userProvider, 'loadUserByIdentifier')) {
trigger_deprecation('symfony/security-core', '5.3', 'Not implementing method "loadUserByIdentifier()" in user provider "%s" is deprecated. This method will replace "loadUserByUsername()" in Symfony 6.0.', get_debug_type($this->userProvider));
$method = 'loadUserByUsername';
}
return new SelfValidatingPassport(
new UserBadge($request->attributes->get('_pre_authenticated_username'), [$this->userProvider, $method]),
[new PreAuthenticatedUserBadge()]
);
}
public function createAuthenticatedToken(PassportInterface $passport, string $firewallName): TokenInterface

View File

@ -46,7 +46,7 @@ interface AuthenticatorInterface
* presented password and the CSRF token value.
*
* You may throw any AuthenticationException in this method in case of error (e.g.
* a UsernameNotFoundException when the user cannot be found).
* a UserNotFoundException when the user cannot be found).
*
* @throws AuthenticationException
*/

View File

@ -84,14 +84,19 @@ class FormLoginAuthenticator extends AbstractLoginFormAuthenticator
{
$credentials = $this->getCredentials($request);
$passport = new Passport(new UserBadge($credentials['username'], function ($username) {
$user = $this->userProvider->loadUserByUsername($username);
if (!$user instanceof UserInterface) {
throw new AuthenticationServiceException('The user provider must return a UserInterface object.');
}
// @deprecated since 5.3, change to $this->userProvider->loadUserByIdentifier() in 6.0
$method = 'loadUserByIdentifier';
if (!method_exists($this->userProvider, 'loadUserByIdentifier')) {
trigger_deprecation('symfony/security-core', '5.3', 'Not implementing method "loadUserByIdentifier()" in user provider "%s" is deprecated. This method will replace "loadUserByUsername()" in Symfony 6.0.', get_debug_type($this->userProvider));
return $user;
}), new PasswordCredentials($credentials['password']), [new RememberMeBadge()]);
$method = 'loadUserByUsername';
}
$passport = new Passport(
new UserBadge($credentials['username'], [$this->userProvider, $method]),
new PasswordCredentials($credentials['password']),
[new RememberMeBadge()]
);
if ($this->options['enable_csrf']) {
$passport->addBadge(new CsrfTokenBadge($this->options['csrf_token_id'], $credentials['csrf_token']));
}

View File

@ -67,14 +67,18 @@ class HttpBasicAuthenticator implements AuthenticatorInterface, AuthenticationEn
$username = $request->headers->get('PHP_AUTH_USER');
$password = $request->headers->get('PHP_AUTH_PW', '');
$passport = new Passport(new UserBadge($username, function ($username) {
$user = $this->userProvider->loadUserByUsername($username);
if (!$user instanceof UserInterface) {
throw new AuthenticationServiceException('The user provider must return a UserInterface object.');
}
// @deprecated since 5.3, change to $this->userProvider->loadUserByIdentifier() in 6.0
$method = 'loadUserByIdentifier';
if (!method_exists($this->userProvider, 'loadUserByIdentifier')) {
trigger_deprecation('symfony/security-core', '5.3', 'Not implementing method "loadUserByIdentifier()" in user provider "%s" is deprecated. This method will replace "loadUserByUsername()" in Symfony 6.0.', get_debug_type($this->userProvider));
return $user;
}), new PasswordCredentials($password));
$method = 'loadUserByUsername';
}
$passport = new Passport(
new UserBadge($username, [$this->userProvider, $method]),
new PasswordCredentials($password)
);
if ($this->userProvider instanceof PasswordUpgraderInterface) {
$passport->addBadge(new PasswordUpgradeBadge($password, $this->userProvider));
}

View File

@ -94,14 +94,18 @@ class JsonLoginAuthenticator implements InteractiveAuthenticatorInterface
throw $e;
}
$passport = new Passport(new UserBadge($credentials['username'], function ($username) {
$user = $this->userProvider->loadUserByUsername($username);
if (!$user instanceof UserInterface) {
throw new AuthenticationServiceException('The user provider must return a UserInterface object.');
}
// @deprecated since 5.3, change to $this->userProvider->loadUserByIdentifier() in 6.0
$method = 'loadUserByIdentifier';
if (!method_exists($this->userProvider, 'loadUserByIdentifier')) {
trigger_deprecation('symfony/security-core', '5.3', 'Not implementing method "loadUserByIdentifier()" in user provider "%s" is deprecated. This method will replace "loadUserByUsername()" in Symfony 6.0.', get_debug_type($this->userProvider));
return $user;
}), new PasswordCredentials($credentials['password']));
$method = 'loadUserByUsername';
}
$passport = new Passport(
new UserBadge($credentials['username'], [$this->userProvider, $method]),
new PasswordCredentials($credentials['password'])
);
if ($this->userProvider instanceof PasswordUpgraderInterface) {
$passport->addBadge(new PasswordUpgradeBadge($credentials['password'], $this->userProvider));
}

View File

@ -11,7 +11,7 @@
namespace Symfony\Component\Security\Http\Authenticator\Passport\Badge;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\Exception\AuthenticationServiceException;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Http\EventListener\UserProviderListener;
@ -40,7 +40,7 @@ class UserBadge implements BadgeInterface
* based on email *and* company name). This string can be used for e.g. login throttling.
*
* Optionally, you may pass a user loader. This callable receives the $userIdentifier
* as argument and must return a UserInterface object (otherwise a UsernameNotFoundException
* as argument and must return a UserInterface object (otherwise an AuthenticationServiceException
* is thrown). If this is not set, the default user provider will be used with
* $userIdentifier as username.
*/
@ -64,7 +64,7 @@ class UserBadge implements BadgeInterface
$this->user = ($this->userLoader)($this->userIdentifier);
if (!$this->user instanceof UserInterface) {
throw new UsernameNotFoundException();
throw new AuthenticationServiceException(sprintf('The user provider must return a UserInterface object, "%s" given.', \get_debug_type($this->user)));
}
}

View File

@ -82,7 +82,8 @@ class RememberMeAuthenticator implements InteractiveAuthenticatorInterface
throw new \LogicException('No remember me token is set.');
}
return new SelfValidatingPassport(new UserBadge($token->getUsername(), [$token, 'getUser']));
// @deprecated since 5.3, change to $token->getUserIdentifier() in 6.0
return new SelfValidatingPassport(new UserBadge(method_exists($token, 'getUserIdentifier') ? $token->getUserIdentifier() : $token->getUsername(), [$token, 'getUser']));
}
public function createAuthenticatedToken(PassportInterface $passport, string $firewallName): TokenInterface

View File

@ -46,6 +46,13 @@ class UserProviderListener
return;
}
$badge->setUserLoader([$this->userProvider, 'loadUserByUsername']);
// @deprecated since 5.3, change to $this->userProvider->loadUserByIdentifier() in 6.0
if (method_exists($this->userProvider, 'loadUserByIdentifier')) {
$badge->setUserLoader([$this->userProvider, 'loadUserByIdentifier']);
} else {
trigger_deprecation('symfony/security-http', '5.3', 'Not implementing method "loadUserByIdentifier()" in user provider "%s" is deprecated. This method will replace "loadUserByUsername()" in Symfony 6.0.', get_debug_type($this->userProvider));
$badge->setUserLoader([$this->userProvider, 'loadUserByUsername']);
}
}
}

View File

@ -195,7 +195,8 @@ abstract class AbstractAuthenticationListener extends AbstractListener
private function onSuccess(Request $request, TokenInterface $token): Response
{
if (null !== $this->logger) {
$this->logger->info('User has been authenticated successfully.', ['username' => $token->getUsername()]);
// @deprecated since 5.3, change to $token->getUserIdentifier() in 6.0
$this->logger->info('User has been authenticated successfully.', ['username' => method_exists($token, 'getUserIdentifier') ? $token->getUserIdentifier() : $token->getUsername()]);
}
$this->tokenStorage->setToken($token);

View File

@ -83,7 +83,8 @@ abstract class AbstractPreAuthenticatedListener extends AbstractListener
}
if (null !== $token = $this->tokenStorage->getToken()) {
if ($token instanceof PreAuthenticatedToken && $this->providerKey == $token->getFirewallName() && $token->isAuthenticated() && $token->getUsername() === $user) {
// @deprecated since 5.3, change to $token->getUserIdentifier() in 6.0
if ($token instanceof PreAuthenticatedToken && $this->providerKey == $token->getFirewallName() && $token->isAuthenticated() && (method_exists($token, 'getUserIdentifier') ? $token->getUserIdentifier() : $token->getUsername()) === $user) {
return;
}
}

View File

@ -73,7 +73,8 @@ class BasicAuthenticationListener extends AbstractListener
}
if (null !== $token = $this->tokenStorage->getToken()) {
if ($token instanceof UsernamePasswordToken && $token->isAuthenticated() && $token->getUsername() === $username) {
// @deprecated since 5.3, change to $token->getUserIdentifier() in 6.0
if ($token instanceof UsernamePasswordToken && $token->isAuthenticated() && (method_exists($token, 'getUserIdentifier') ? $token->getUserIdentifier() : $token->getUsername()) === $username) {
return;
}
}

View File

@ -27,7 +27,7 @@ use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInt
use Symfony\Component\Security\Core\Authentication\Token\SwitchUserToken;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\Exception\UserNotFoundException;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Http\Event\DeauthenticatedEvent;
@ -222,7 +222,8 @@ class ContextListener extends AbstractListener
$userDeauthenticated = true;
if (null !== $this->logger) {
$this->logger->debug('Cannot refresh token because user has changed.', ['username' => $refreshedUser->getUsername(), 'provider' => \get_class($provider)]);
// @deprecated since 5.3, change to $refreshedUser->getUserIdentifier() in 6.0
$this->logger->debug('Cannot refresh token because user has changed.', ['username' => method_exists($refreshedUser, 'getUserIdentifier') ? $refreshedUser->getUserIdentifier() : $refreshedUser->getUsername(), 'provider' => \get_class($provider)]);
}
continue;
@ -231,10 +232,12 @@ class ContextListener extends AbstractListener
$token->setUser($refreshedUser);
if (null !== $this->logger) {
$context = ['provider' => \get_class($provider), 'username' => $refreshedUser->getUsername()];
// @deprecated since 5.3, change to $refreshedUser->getUserIdentifier() in 6.0
$context = ['provider' => \get_class($provider), 'username' => method_exists($refreshedUser, 'getUserIdentifier') ? $refreshedUser->getUserIdentifier() : $refreshedUser->getUsername()];
if ($token instanceof SwitchUserToken) {
$context['impersonator_username'] = $token->getOriginalToken()->getUsername();
// @deprecated since 5.3, change to $token->getUserIdentifier() in 6.0
$context['impersonator_username'] = method_exists($token, 'getUserIdentifier') ? $token->getUserIdentifier() : $token->getOriginalToken()->getUsername();
}
$this->logger->debug('User was reloaded from a user provider.', $context);
@ -243,9 +246,9 @@ class ContextListener extends AbstractListener
return $token;
} catch (UnsupportedUserException $e) {
// let's try the next user provider
} catch (UsernameNotFoundException $e) {
} catch (UserNotFoundException $e) {
if (null !== $this->logger) {
$this->logger->warning('Username could not be found in the selected user provider.', ['username' => $e->getUsername(), 'provider' => \get_class($provider)]);
$this->logger->warning('Username could not be found in the selected user provider.', ['username' => method_exists($e, 'getUserIdentifier') ? $e->getUserIdentifier() : $e->getUsername(), 'provider' => \get_class($provider)]);
}
$userNotFoundByProvider = true;

Some files were not shown because too many files have changed in this diff Show More