更改内存中提供程序的默认用户对象
Changing default User object for in-memory provider
我只是想更改内存中提供程序的默认 User
对象。默认 User
对象是 Symfony\Component\Security\Core\User\User
。但是这个对象不符合我的要求,所以我复制了那个对象并为我的要求添加了一些属性然后将它命名为 InMemoryUser
并像下面这样使用它:
encoders:
App\Component\Security\Core\User\InMemoryUser: plaintext
然后我在尝试 运行 应用程序时遇到以下错误。
No encoder has been configured for account "App\Component\Security\Core\User\InMemoryUser"
查了大概半个小时才发现问题。 Symfony 默认调用 Symfony\Component\Security\Core\User\InMemoryUserProvider
并使用 Symfony\Component\Security\Core\User\User
对象在 __construct
方法中创建内存用户。
然后我尝试如下覆盖默认 InMemoryUserProvider
。
services:
App\Component\Security\Core\User\CustomInMemoryUserProvider:
decorates: security.user.provider.concrete.api_user_provider
arguments:
$users: [] # this should be contains in-memory users defined in the security.yaml but i dont know how to do that.
这工作正常,除了一个小问题,不会像 InMemoryUserProvider
那样注入 $users
。通常,$users
包含在 security.yaml
.
中定义的内存中用户列表
现在,我如何为我的 CustomInMemoryUserProvider
注入 $users
,这是为 InMemoryProvider
更改 User
对象的好习惯吗?
提前感谢您的回答。
顺便说一句,我正在使用symfony 5.1
。
我从来没有完全破解过正确装饰其构造函数由 DI 扩展动态注入的服务的奥秘。
但是,在这种情况下,您真正需要做的就是更改内存提供程序的 class,这可以在内核中的编译器传递中完成:
# src\Kernel.php
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use App\User\InMemoryUserProvider;
class Kernel extends BaseKernel implements CompilerPassInterface
...
public function process(ContainerBuilder $container)
{
$id = 'security.user.provider.in_memory';
$container->getDefinition($id)->setClass(InMemoryUserProvider::class);
}
测试时,我最初尝试扩展内存提供程序中的现有核心,但它使用无法覆盖的私有方法。所以我只是重新实现了完整的接口
namespace App\User;
class InMemoryUserProvider implements UserProviderInterface
{
public function __construct(array $users)
{
dump($users); // Confirms get the users from security.yaml
}
public function loadUserByUsername(string $username)
{
// TODO: Implement loadUserByUsername() method.
echo "Get User {$username}\n";
}
确认已按预期接线:
bin/console debug:container | grep UserProv
App\User\InMemoryUserProvider = App\User\InMemoryUserProvider
Symfony\Component\Security\Core\User\UserProviderInterface = alias for "security.user.provider.concrete.users_in_memory"
security.user.provider.concrete.users_in_memory = App\User\InMemoryUserProvider
security.user.provider.in_memory = App\User\InMemoryUserProvider
并发出一个命令来验证它是否按预期工作:
class UserProviderCommand extends Command
{
protected static $defaultName = 'user:provider';
private $userProvider;
public function __construct(UserProviderInterface $userProvider)
{
parent::__construct();
$this->userProvider = $userProvider;
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
echo "User Provider: " . get_class($this->userProvider) . "\n";
$this->userProvider->loadUserByUsername('xxx');
return 0;
}
}
我只是想更改内存中提供程序的默认 User
对象。默认 User
对象是 Symfony\Component\Security\Core\User\User
。但是这个对象不符合我的要求,所以我复制了那个对象并为我的要求添加了一些属性然后将它命名为 InMemoryUser
并像下面这样使用它:
encoders:
App\Component\Security\Core\User\InMemoryUser: plaintext
然后我在尝试 运行 应用程序时遇到以下错误。
No encoder has been configured for account "App\Component\Security\Core\User\InMemoryUser"
查了大概半个小时才发现问题。 Symfony 默认调用 Symfony\Component\Security\Core\User\InMemoryUserProvider
并使用 Symfony\Component\Security\Core\User\User
对象在 __construct
方法中创建内存用户。
然后我尝试如下覆盖默认 InMemoryUserProvider
。
services:
App\Component\Security\Core\User\CustomInMemoryUserProvider:
decorates: security.user.provider.concrete.api_user_provider
arguments:
$users: [] # this should be contains in-memory users defined in the security.yaml but i dont know how to do that.
这工作正常,除了一个小问题,不会像 InMemoryUserProvider
那样注入 $users
。通常,$users
包含在 security.yaml
.
现在,我如何为我的 CustomInMemoryUserProvider
注入 $users
,这是为 InMemoryProvider
更改 User
对象的好习惯吗?
提前感谢您的回答。
顺便说一句,我正在使用symfony 5.1
。
我从来没有完全破解过正确装饰其构造函数由 DI 扩展动态注入的服务的奥秘。
但是,在这种情况下,您真正需要做的就是更改内存提供程序的 class,这可以在内核中的编译器传递中完成:
# src\Kernel.php
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use App\User\InMemoryUserProvider;
class Kernel extends BaseKernel implements CompilerPassInterface
...
public function process(ContainerBuilder $container)
{
$id = 'security.user.provider.in_memory';
$container->getDefinition($id)->setClass(InMemoryUserProvider::class);
}
测试时,我最初尝试扩展内存提供程序中的现有核心,但它使用无法覆盖的私有方法。所以我只是重新实现了完整的接口
namespace App\User;
class InMemoryUserProvider implements UserProviderInterface
{
public function __construct(array $users)
{
dump($users); // Confirms get the users from security.yaml
}
public function loadUserByUsername(string $username)
{
// TODO: Implement loadUserByUsername() method.
echo "Get User {$username}\n";
}
确认已按预期接线:
bin/console debug:container | grep UserProv
App\User\InMemoryUserProvider = App\User\InMemoryUserProvider
Symfony\Component\Security\Core\User\UserProviderInterface = alias for "security.user.provider.concrete.users_in_memory"
security.user.provider.concrete.users_in_memory = App\User\InMemoryUserProvider
security.user.provider.in_memory = App\User\InMemoryUserProvider
并发出一个命令来验证它是否按预期工作:
class UserProviderCommand extends Command
{
protected static $defaultName = 'user:provider';
private $userProvider;
public function __construct(UserProviderInterface $userProvider)
{
parent::__construct();
$this->userProvider = $userProvider;
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
echo "User Provider: " . get_class($this->userProvider) . "\n";
$this->userProvider->loadUserByUsername('xxx');
return 0;
}
}