php - Symfony token 在订阅者中为空

标签 php symfony service token

我为需要访问当前登录用户的 prePersist 和 preFlush 事件创建了一个监听器:

<?php

namespace 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 Symfony\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;
    }

    /**
     * @param LifecycleEventArgs $args
     */
    public function preUpdate(LifecycleEventArgs $args)
    {
        if ($args->getObject() instanceof AbstractEntity) {
            $args->getObject()->setUpdateUser($this->getuser()->getLastName() . ' ' . $this->getuser()->getLastName() . ' (' . $this->getuser()->getId() . ')');
        }
    }
}

但 token 始终为空。

所以我对 Controller 中存在的内容进行了一些验证:


    /**
     * @Route("/create", name="create")
     * @param Request $request
     * @param TrainingManager $trainingManager
     * @return Response
     */
    public function create(Request $request, TrainingManager $trainingManager)
    {
        $training = new Training();
        $form = $this->createForm(FormNameType::class, $training);
        $form->handleRequest($request);
        if ($form->isSubmitted() && $form->isValid()) {
                $user = $this->getUser();
                $trainingManager->save($training);
        }
        return $this->render('create.html.twig', ['form' => $form->createView(),]);
    }

并且可以使用 $this->getUser(); 很好地检索用户; 紧接着,我的 dataBaseSubscriber 启动了,并且在构造函数中 token 为空。实际上是相同的标记。

我检查了“security.token_storage”是否正确 Autowiring ,我也试图在 service.yml 中强制它

这让我很困惑。 UsageTrackingStorage 的这两个实例之间的唯一区别是一个在 Controller 中使用,另一个在订阅者中使用。但它应该注入(inject)相同的实例......

最佳答案

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

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

所以当 getToken() 被调用时,它返回 null,因为它不持有任何 token ,但这些 token 是稍后添加的。

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

关于php - Symfony token 在订阅者中为空,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62381937/

相关文章:

php - 扩展表达语言

google-app-engine - 谷歌应用引擎 : a single backend service/module?

php - 空字符串不等于 PHP 三元运算符表达式中的空字符串

php - mysql 获取数组(LIKE%)

php - 从数据库中删除/删除

php - 无法在在线服务器上的 Lamp 中连接 mysql 和 php

unit-testing - Selenium 2 (WebDriver) 和 Phpunit 与 Symfony 2.1 的最佳 bundle

forms - 标签选择表单中的 HTML

android - 读取服务中 Activity 存储的 SharedPreferences?

android - 每当我检查服务是否在 android 中运行时,它总是说不