[Security] Fix BC layer

This commit is contained in:
Robin Chalas 2021-03-16 21:07:52 +01:00
parent db87d72869
commit 2d7f7b5072
7 changed files with 58 additions and 110 deletions

View File

@ -12,8 +12,8 @@
namespace Symfony\Bundle\SecurityBundle\Tests\Functional;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Core\User\InMemoryUser;
use Symfony\Component\Security\Core\User\InMemoryUserProvider;
use Symfony\Component\Security\Core\User\User;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
@ -73,7 +73,7 @@ class RememberMeUserProvider implements UserProviderInterface
{
$user = $this->inner->refreshUser($user);
$alterUser = \Closure::bind(function (InMemoryUser $user) { $user->password = 'foo'; }, null, InMemoryUser::class);
$alterUser = \Closure::bind(function (User $user) { $user->password = 'foo'; }, null, User::class);
$alterUser($user);
return $user;

View File

@ -19,6 +19,7 @@ use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasher;
use Symfony\Component\PasswordHasher\PasswordHasherInterface;
use Symfony\Component\Security\Core\User\InMemoryUser;
use Symfony\Component\Security\Core\User\LegacyPasswordAuthenticatedUserInterface;
use Symfony\Component\Security\Core\User\User;
use Symfony\Component\Security\Core\User\UserInterface;
class UserPasswordHasherTest extends TestCase
@ -121,7 +122,7 @@ class UserPasswordHasherTest extends TestCase
$passwordHasher = new UserPasswordHasher($mockPasswordHasherFactory);
\Closure::bind(function () use ($passwordHasher) { $this->password = $passwordHasher->hashPassword($this, 'foo', 'salt'); }, $user, InMemoryUser::class)();
\Closure::bind(function () use ($passwordHasher) { $this->password = $passwordHasher->hashPassword($this, 'foo', 'salt'); }, $user, User::class)();
$this->assertFalse($passwordHasher->needsRehash($user));
$this->assertTrue($passwordHasher->needsRehash($user));
$this->assertFalse($passwordHasher->needsRehash($user));

View File

@ -74,7 +74,7 @@ class InMemoryUserProviderTest extends TestCase
public function testCreateUser()
{
$provider = new InMemoryUserProvider();
$provider->createUser(new User('fabien', 'foo'));
$provider->createUser(new InMemoryUser('fabien', 'foo'));
$user = $provider->loadUserByUsername('fabien');
$this->assertEquals('foo', $user->getPassword());
@ -84,8 +84,8 @@ class InMemoryUserProviderTest extends TestCase
{
$this->expectException(\LogicException::class);
$provider = new InMemoryUserProvider();
$provider->createUser(new User('fabien', 'foo'));
$provider->createUser(new User('fabien', 'foo'));
$provider->createUser(new InMemoryUser('fabien', 'foo'));
$provider->createUser(new InMemoryUser('fabien', 'foo'));
}
public function testLoadUserByUsernameDoesNotExist()

View File

@ -19,115 +19,58 @@ namespace Symfony\Component\Security\Core\User;
* @author Robin Chalas <robin.chalas@gmail.com>
* @author Fabien Potencier <fabien@symfony.com>
*/
final class InMemoryUser implements UserInterface, PasswordAuthenticatedUserInterface, EquatableInterface
final class InMemoryUser extends User
{
private $username;
private $password;
private $enabled;
private $roles;
/**
* @param string[] $roles
*/
public function __construct(string $username, ?string $password, array $roles = [], bool $enabled = true)
{
if ('' === $username) {
throw new \InvalidArgumentException('The username cannot be empty.');
}
$this->username = $username;
$this->password = $password;
$this->roles = $roles;
$this->enabled = $enabled;
}
public function __toString(): string
{
return $this->getUsername();
}
/**
* {@inheritdoc}
*/
public function getRoles(): array
{
return $this->roles;
}
/**
* {@inheritdoc}
*/
public function getPassword(): ?string
{
return $this->password;
}
/**
* {@inheritdoc}
*/
public function getSalt(): ?string
{
return null;
}
/**
* {@inheritdoc}
*/
public function getUsername(): string
{
return $this->username;
}
/**
* Checks whether the user is enabled.
*
* Internally, if this method returns false, the authentication system
* will throw a DisabledException and prevent login.
*
* @return bool true if the user is enabled, false otherwise
*
* @see DisabledException
* @deprecated since Symfony 5.3
*/
public function isEnabled(): bool
public function isAccountNonExpired(): bool
{
return $this->enabled;
trigger_deprecation('symfony/security-core', '5.3', 'Method "%s()" is deprecated, you should stop using it.', __METHOD__);
return parent::isAccountNonExpired();
}
/**
* {@inheritdoc}
*
* @deprecated since Symfony 5.3
*/
public function eraseCredentials()
public function isAccountNonLocked(): bool
{
trigger_deprecation('symfony/security-core', '5.3', 'Method "%s()" is deprecated, you should stop using it.', __METHOD__);
return parent::isAccountNonLocked();
}
/**
* {@inheritdoc}
*
* @deprecated since Symfony 5.3
*/
public function isEqualTo(UserInterface $user): bool
public function isCredentialsNonExpired(): bool
{
if (!$user instanceof self) {
return false;
trigger_deprecation('symfony/security-core', '5.3', 'Method "%s()" is deprecated, you should stop using it.', __METHOD__);
return parent::isCredentialsNonExpired();
}
if ($this->getPassword() !== $user->getPassword()) {
return false;
/**
* @deprecated since Symfony 5.3
*/
public function getExtraFields(): array
{
trigger_deprecation('symfony/security-core', '5.3', 'Method "%s()" is deprecated, you should stop using it.', __METHOD__);
return parent::getExtraFields();
}
$currentRoles = array_map('strval', (array) $this->getRoles());
$newRoles = array_map('strval', (array) $user->getRoles());
$rolesChanged = \count($currentRoles) !== \count($newRoles) || \count($currentRoles) !== \count(array_intersect($currentRoles, $newRoles));
if ($rolesChanged) {
return false;
}
public function setPassword(string $password)
{
trigger_deprecation('symfony/security-core', '5.3', 'Method "%s()" is deprecated, you should stop using it.', __METHOD__);
if ($this->getUsername() !== $user->getUsername()) {
return false;
}
if ($this->isEnabled() !== $user->isEnabled()) {
return false;
}
return true;
parent::setPassword($password);
}
}

View File

@ -38,7 +38,7 @@ class InMemoryUserChecker implements UserCheckerInterface
}
// @deprecated since Symfony 5.3
if ($user instanceof User) {
if (User::class === \get_class($user)) {
if (!$user->isAccountNonLocked()) {
$ex = new LockedException('User account is locked.');
$ex->setUser($user);
@ -56,7 +56,7 @@ class InMemoryUserChecker implements UserCheckerInterface
public function checkPostAuth(UserInterface $user)
{
// @deprecated since Symfony 5.3, noop in 6.0
if (!$user instanceof User) {
if (User::class !== \get_class($user)) {
return;
}

View File

@ -80,8 +80,8 @@ class InMemoryUserProvider implements UserProviderInterface
$storedUser = $this->getUser($user->getUsername());
// @deprecated since Symfony 5.3
if ($user instanceof User) {
if (!$storedUser instanceof User) {
if (User::class === \get_class($user)) {
if (User::class !== \get_class($storedUser)) {
$accountNonExpired = true;
$credentialsNonExpired = $storedUser->getPassword() === $user->getPassword();
$accountNonLocked = true;

View File

@ -11,8 +11,6 @@
namespace Symfony\Component\Security\Core\User;
trigger_deprecation('symfony/security-core', '5.3', 'The "%s" class is deprecated, use "%s" instead.', User::class, InMemoryUser::class);
/**
* User is the user implementation used by the in-memory user provider.
*
@ -22,7 +20,7 @@ trigger_deprecation('symfony/security-core', '5.3', 'The "%s" class is deprecate
*
* @deprecated since Symfony 5.3, use {@link InMemoryUser} instead
*/
final class User implements UserInterface, PasswordAuthenticatedUserInterface, EquatableInterface
class User implements UserInterface, PasswordAuthenticatedUserInterface, EquatableInterface
{
private $username;
private $password;
@ -35,6 +33,10 @@ final class User implements UserInterface, PasswordAuthenticatedUserInterface, E
public function __construct(?string $username, ?string $password, array $roles = [], bool $enabled = true, bool $userNonExpired = true, bool $credentialsNonExpired = true, bool $userNonLocked = true, array $extraFields = [])
{
if (InMemoryUser::class !== static::class) {
trigger_deprecation('symfony/security-core', '5.3', 'The "%s" class is deprecated, use "%s" instead.', self::class, InMemoryUser::class);
}
if ('' === $username || null === $username) {
throw new \InvalidArgumentException('The username cannot be empty.');
}
@ -186,6 +188,7 @@ final class User implements UserInterface, PasswordAuthenticatedUserInterface, E
return false;
}
if (self::class === static::class) {
if ($this->isAccountNonExpired() !== $user->isAccountNonExpired()) {
return false;
}
@ -197,6 +200,7 @@ final class User implements UserInterface, PasswordAuthenticatedUserInterface, E
if ($this->isCredentialsNonExpired() !== $user->isCredentialsNonExpired()) {
return false;
}
}
if ($this->isEnabled() !== $user->isEnabled()) {
return false;