我最终做了两件事:
- 覆盖属性的标记设置器和获取器
user
- 使用 Doctrine
LifecycleEvent
监听器
首先扩展令牌类(例如使用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 }
用户对象现在应该始终附加到令牌