【问题标题】:Changing default User object for in-memory provider更改内存提供程序的默认用户对象
【发布时间】:2020-07-03 20:11:53
【问题描述】:

我只是想更改内存中提供程序的默认 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,这是将User 对象更改为InMemoryProvider 的好习惯吗?

提前感谢您的回答。

顺便说一句,我正在使用symfony 5.1

【问题讨论】:

    标签: php symfony dependency-injection symfony5


    【解决方案1】:

    我从来没有完全破解过正确装饰其构造函数由 DI 扩展动态注入的服务的奥秘。

    但是,在这种情况下,您真正​​需要做的就是更改内存提供程序的类,这可以在内核中的编译器传递中完成:

    # 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;
        }
    }
    

    【讨论】:

    • 感谢@Cerad!它可以按我的意愿工作。痴迷和野心创造了这个谜团:) 从错误的角度看太多可能是忽视看到另一个孤独的理由。就像我一样。再次感谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-28
    • 2015-06-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-01
    相关资源
    最近更新 更多