为了账号安全,请及时绑定邮箱和手机立即绑定

Symfony 令牌在订阅者中为空

Symfony 令牌在订阅者中为空

PHP
森林海 2023-05-26 17:23:54
我为需要访问当前登录用户的 prePersist 和 preFlush 事件创建了一个监听器:<?phpnamespace App\EventListener;use App\Entity\AbstractEntity;use App\Entity\User;use Doctrine\Common\EventSubscriber;use Doctrine\ORM\Events;use Doctrine\Persistence\Event\LifecycleEventArgs;use Exception;use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;use Syfony\Component\Security\Core\User\UserInterface;use function is_object;class DatabaseActivitySubscriber implements EventSubscriber{    /**     * @var TokenInterface|null     */    private ?TokenInterface $token;    public function __construct(TokenStorageInterface $tokenStorage)    {        $this->token = $tokenStorage->getToken();    }    /**     * @return array|string[]     */    public function getSubscribedEvents()    {        return [            Events::prePersist,            Events::preUpdate,        ];    }    /**     * Initialise le nom de l'utilisateur a l'origine de la création sous la forme "Nom Prénom (id)"     *     * @param LifecycleEventArgs $args     * @throws Exception     */    public function prePersist(LifecycleEventArgs $args)    {        if ($args->getObject() instanceof AbstractEntity) {            $args->getObject()->setCreateUser($this->getUser()->getLastName() . ' ' . $this->getuser()->getLastName() . ' (' . $this->getuser()->getId() . ')');        }    }    /**     * @return string|\Stringable|UserInterface|null|User     */    private function getUser()    {        if (null === $token = $this->token) {            return null;        }        if (!is_object($user = $token->getUser())) {            // e.g. anonymous authentication            return null;        }        return $user;    }但令牌始终为空。并且用户可以通过 $this->getUser(); 很好地检索到。紧接着,我的 dataBaseSubscriber 启动了,并且在构造函数中令牌为空。实际上是相同的标记。我检查了“security.token_storage”是否正确自动装配,我也试图在 service.yml 中强制它这让我很困惑。UsageTrackingStorage 的这两个实例之间的唯一区别是一个在控制器中使用,另一个在订阅者中使用。但它应该注入相同的实例......
查看完整描述

1 回答

?
哔哔one

TA贡献1854条经验 获得超8个赞

订阅者(如您的订阅者)很可能在请求生命周期的早期就已初始化。也就是说,在为所有授权内容拆分请求之前。

TokenStorage 是正确的,但是,在您的订阅者初始化(读取:被调用)的那一刻,__construct除了对象本身之外几乎什么都不存在,但它仍然是空的(显然)。有/可以有 EventSubscribers 可以更改身份验证过程,所以如果令牌已经存在,那将是荒谬的。(事实上我相信 symfony 中的授权是通过 EventListeners 完成的)。

因此,当在该点上getToken()调用它时,它返回 null,因为它不包含任何令牌,但稍后会添加这些令牌。

解决方案非常简单:只需存储 TokenStorage - 而不是(空)令牌 - 并在您实际需要它时稍后调用“getToken”并且其中实际上有令牌。开销几乎可以忽略不计(缓存可能是可能的,但没有看到一个很好的理由)。


查看完整回答
反对 回复 2023-05-26
  • 1 回答
  • 0 关注
  • 92 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信