我正在本地开发一个小型 symfony 项目。我正在使用码头工人。我使用 symfony 4.3.8 我决定更新 symfony,在使用docker-compose run --rm manager-php-cli composer update 命令后,symfony以及所有软件包都更新到了 4.3.11
之后,之前运行良好的用户授权在尝试登录时出现错误:
There is no user provider for user "App\Security\UserIdentity". Shouldn't the "supportsClass()" method of your user provider return true for this classname?
多次清除缓存。尝试了缓存:清除和手动。
可能是什么问题呢?真的可以通过简单的更新来破坏项目吗?这是我的 security.yaml
security:
# https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers
providers:
fetcher:
id: App\Security\UserProvider
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
anonymous: true
user_checker: App\Security\UserChecker
guard:
authenticators:
- App\Security\LoginFormAuthenticator
- App\Security\OAuth\FacebookAuthenticator
entry_point: App\Security\LoginFormAuthenticator
remember_me:
secret: '%kernel.secret%'
lifetime: 604800
path: /
form_login: true
logout:
path: app_logout
# where to redirect after logout
# target: app_any_route
# activate different ways to authenticate
# https://symfony.com/doc/current/security.html#firewalls-authentication
# https://symfony.com/doc/current/security/impersonating_user.html
# switch_user: true
role_hierarchy:
ROLE_ADMIN:
- ROLE_USER
- ROLE_MANAGE_USERS
- ROLE_WORK_MANAGE_MEMBERS
- ROLE_WORK_MANAGE_PROJECTS
# Easy way to control access for large sections of your site
# Note: Only the *first* access control that matches will be used
access_control:
- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/signup, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/reset, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/oauth, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/, roles: ROLE_USER }
这是 UserProvider.php
declare(strict_types=1);
namespace App\Security;
use App\ReadModel\User\AuthView;
use App\ReadModel\User\UserFetcher;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
class UserProvider implements UserProviderInterface
{
/**
* @var UserFetcher
*/
private $users;
public function __construct(UserFetcher $users)
{
$this->users = $users;
}
public function loadUserByUsername($username): UserInterface
{
$user = $this->loadUser($username); // $username can be useremail@gmail.com or facebook:56474756967544769
return self::identityByUser($user, $username);
}
public function refreshUser(UserInterface $identity): UserInterface
{
if(!$identity instanceof UserIdentity){
throw new UnsupportedUserException('Invalid user class '.get_class($identity));
}
$user = $this->loadUser($identity->getUsername());
return self::identityByUser($user, $identity->getUsername());
}
public function supportsClass($class): bool
{
return $class instanceof UserIdentity;
}
private function loadUser($username): AuthView
{
$chunks = explode(":", $username); // $username can be useremail@gmail.com or facebook:56474756967544769
if(count($chunks) === 2 && $user = $this->users->findForAuthByNetwork($chunks[0], $chunks[1])){
return $user;
}
if( ! $user = $this->users->findForAuthByEmail($username) ){
throw new UsernameNotFoundException("");
}
return $user;
}
/**
* $username must be:
* facebook:56474756967544769
* or useremail@gmail.com
*
* @param AuthView $user
* @param string $username - т.к. при регистрации через соц. сеть email может быть пустым, пишем сюда $username, который может быть вида: useremail@gmail.com or facebook:56474756967544769
* @return UserIdentity
*/
private static function identityByUser(AuthView $user, string $username): UserIdentity
{
return new UserIdentity(
$user->id,
$user->email ?: $username,
$user->password_hash ?: '',
$user->name ?: $username,
$user->role,
$user->status
);
}
}
这是 UserIdentity.php
declare(strict_types=1);
namespace App\Security;
use App\Model\User\Entity\User\User;
use Symfony\Component\Security\Core\User\EquatableInterface;
use Symfony\Component\Security\Core\User\UserInterface;
class UserIdentity implements UserInterface, EquatableInterface
{
/**
* @var string
*/
private $id;
/**
* @var string
*/
private $username;
/**
* @var string
*/
private $password;
/**
* @var string
*/
private $display;
/**
* @var string
*/
private $role;
/**
* @var string
*/
private $status;
public function __construct(string $id, string $username, string $password, string $display, string $role, string $status)
{
$this->id = $id;
$this->username = $username;
$this->password = $password;
$this->display = $display;
$this->role = $role;
$this->status = $status;
}
public function getId(): string
{
return $this->id;
}
public function getUsername(): string
{
return $this->username;
}
public function getPassword(): string
{
return $this->password;
}
public function getDisplay(): string
{
return $this->display;
}
public function getRoles(): array
{
return [$this->role];
}
public function getStatus(): string
{
return $this->status;
}
public function isActive(): bool
{
return $this->status === User::STATUS_ACTIVE;
}
public function getSalt(): ?string
{
return null;
}
public function eraseCredentials(): void
{
return;
}
public function isEqualTo(UserInterface $user): bool
{
if(!$user instanceof self){
return false;
}
return
$this->id === $user->id &&
$this->password === $user->password &&
$this->role === $user->role &&
$this->status === $user->status;
}
}
在 UserProvider 中更新 supportClass 后返回 false
变成