【问题标题】:OAuth2 server with an external user source具有外部用户源的 OAuth2 服务器
【发布时间】:2015-07-23 09:50:48
【问题描述】:

我正在使用出色的 FOSOAuthServerBundle 构建 OAuth2 服务器。

我的 Symfony 应用程序验证来自另一个来源(实际上是另一个服务器)的用户。

我创建了一个自定义的UserProvider,它可以与默认的 Symfony 安全层一起正常工作。我有UserInterface 的实现,但它显然不是数据库的实体。

AccessTokenRefreshTokenAuthCode 的类实现为 Doctrine 的 told in the installation instructions,我将用户引用定义为

//...
/**
 * @ORM\Column(type="integer")
 */
protected $user_id;
//...

直到那里看起来合乎逻辑吗?

现在真正的问题是: 我在哪里指定将我的用户链接到不同令牌的方式?


为了可见性,我还在官方 repo 上asking the question

【问题讨论】:

    标签: php symfony oauth fosoauthserverbundle


    【解决方案1】:

    我最终做了两件事:

    • 覆盖属性user 的标记设置器和获取器
    • 使用 Doctrine LifecycleEvent listener

    首先扩展令牌类(例如使用Trait

    namespace AppBundle\Entity;
    
    use AppBundle\Security\User;
    use Symfony\Component\Security\Core\User\UserInterface;
    
    trait AppTokenTrait
    {
        /**
         * @ORM\Column(type="string")
         * @var string
         */
        protected $username;
    
        public function setUser(UserInterface $user)
        {
            if (!$user instanceof User) {
                throw new \InvalidArgumentException(
                    sprintf("User must be an instance of %s", User::class)
                );
            }
    
            $this->username = $user->getUsername();
            $this->user = $user;
        }
    
        public function getUser()
        {
            if (!$this->user) {
                throw new \RuntimeException(
                    "Unable to get user - user was not loaded by postLoad"
                );
            }
    
            return $this->user;
        }
    
        /**
         * @return string
         */
        public function getUsername()
        {
            return $this->username;
        }
    }
    

    在 3 个令牌类中(并且不要忘记更新数据库架构):

    //...
        use AppTokenTrait;
    //...
    

    创建监听器

    namespace AppBundle\Services;
    
    use AppBundle\Entity\AccessToken;
    use AppBundle\Entity\AuthCode;
    use AppBundle\Entity\RefreshToken;
    use AppBundle\Security\UserProvider;
    use Doctrine\ORM\Event\LifecycleEventArgs;
    
    class AppTokenListener
    {
        /**
         * @var UserProvider
         */
        protected $userProvider;
    
        public function __construct(UserProvider $userProvider)
        {
            $this->userProvider = $userProvider;
        }
    
        public function postLoad(LifecycleEventArgs $event)
        {
            $object = $event->getObject();
    
            if (
                $object instanceof AccessToken or
                $object instanceof AuthCode or
                $object instanceof RefreshToken
            ) {
                $user = $this->userProvider->loadUserByUsername($object->getUsername());
                $object->setUser($user);
            }
        }
    }
    

    注册为服务

    app.token.listener:
        class: AppBundle\Services\AppTokenListener
        tags:
            - { name: doctrine.event_listener, event: postLoad }
    

    现在应该始终将用户对象附加到令牌

    【讨论】:

    • 嗨 Pierre,您的帖子确实帮助我设置了类似的配置。我从 oauth 端启动并运行了所有内容,但是使用访问令牌调用我的 api 会导致致命错误:***/OAuthBundle/Services 上的“错误:调用非对象上的成员函数 loadUserByUsername()” /SecurityTokenListener.php 第 41 行,其中第 41 行是 $user = $this->userProvider->loadUserByUsername($object->getUsername());" 似乎从未调用过构造函数。任何想法,这里发生了什么? 谢谢,克里斯
    • 我只记得在将userProvider 注入侦听器时,这里有一个循环引用问题,我看到这是一个已知问题,我以一种非常肮脏的方式解决了这个问题
    • 现在明白了,服务只需要用户提供者作为参数,而您的 AppTokenListener 在构造函数中缺少“_”。复制/粘贴不是一个好主意:-)
    • 你是如何通过这个循环引用的?
    猜你喜欢
    • 2020-10-19
    • 1970-01-01
    • 2015-04-12
    • 2020-10-28
    • 2023-01-21
    • 2021-03-06
    • 2015-02-18
    • 2022-11-23
    • 2021-09-09
    相关资源
    最近更新 更多