我正在用伟大的FOSOAuthServerBundle构建一个OAuth2服务器。
我的Symfony应用程序验证来自另一个来源(实际上是另一个服务器(的用户。
我已经创建了一个自定义的UserProvider
,它可以很好地与默认的Symfony安全层配合使用。我有UserInterface
的实现,但它显然不是数据库的实体。
实现AccessToken
、RefreshToken
&AuthCode
,如条令安装说明中所述,我将用户参考定义为
//...
/**
* @ORMColumn(type="integer")
*/
protected $user_id;
//...
在那之前,它看起来合乎逻辑吗?
现在真正的问题是:我在哪里指定将用户链接到不同令牌的方式
我也一直在问关于官方回购的问题,以提高可见性
我最终做了两件事:
- 重写令牌setter&属性
user
的getter - 使用条令
LifecycleEvent
监听器
首先扩展令牌类(例如使用Trait(
namespace AppBundleEntity;
use AppBundleSecurityUser;
use SymfonyComponentSecurityCoreUserUserInterface;
trait AppTokenTrait
{
/**
* @ORMColumn(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 AppBundleServices;
use AppBundleEntityAccessToken;
use AppBundleEntityAuthCode;
use AppBundleEntityRefreshToken;
use AppBundleSecurityUserProvider;
use DoctrineORMEventLifecycleEventArgs;
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: AppBundleServicesAppTokenListener
tags:
- { name: doctrine.event_listener, event: postLoad }
用户对象现在应该始终附加到令牌