1

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

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

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

按照 Doctrine的安装说明中的说明,实现AccessToken, RefreshToken&AuthCode的类,我将用户引用定义为

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

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

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


出于可见性目的,我也一直在官方回购中提出问题

4

1 回答 1

1

我最终做了两件事:

  • 覆盖属性的标记设置器和获取器user
  • 使用 DoctrineLifecycleEvent监听器

首先扩展令牌类(例如使用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 }

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

于 2015-07-23T14:49:35.990 回答