如何获取Lexik JWT已编码的JWT令牌字符串?
解决获取编码JWT字符串并存储到数据库的问题
核心问题分析
你当前使用的JWTCreatedEvent是在JWT载荷(payload)创建后、令牌编码前触发的,此时还未生成最终的编码JWT字符串。而tokenStorage中的UsernamePasswordToken是Symfony的身份验证令牌,和JWT令牌并非同一对象,因此无法通过它获取编码后的JWT。
解决方案:监听JWTSuccessEvent
LexikJWTAuthenticationBundle提供的JWTSuccessEvent事件,会在JWT成功编码并准备返回给客户端时触发,该事件直接包含最终的编码JWT字符串。
修改后的代码
<?php namespace App\Security; use App\Entity\Token; use App\Entity\User; use Doctrine\Persistence\ManagerRegistry; use Lexik\Bundle\JWTAuthenticationBundle\Event\JWTSuccessEvent; use Symfony\Component\Security\Core\User\UserInterface; class JWTLogger { private $doctrine; public function __construct(ManagerRegistry $doctrine) { $this->doctrine = $doctrine; } /** * @param JWTSuccessEvent $event * * @return void */ public function onJWTSuccess(JWTSuccessEvent $event) { $encodedToken = $event->getToken(); $user = $event->getUser(); if ($user instanceof UserInterface) { $this->logJWTToken($encodedToken, $user); } } private function logJWTToken(string $encodedToken, User $user): void { $entityManager = $this->doctrine->getManager(); $dbtoken = new Token(); $dbtoken->setToken($encodedToken); // 存入完整的编码JWT字符串 $dbtoken->setUserId($user); $entityManager->persist($dbtoken); $entityManager->flush(); } }
配置事件监听(services.yaml)
在config/services.yaml中注册该事件监听器:
services: App\Security\JWTLogger: tags: - { name: kernel.event_listener, event: lexik_jwt_authentication.on_authentication_success, method: onJWTSuccess }
关键说明
- 移除了不必要的
JWTAuthenticator继承,此类仅作为事件监听器,无需继承身份验证器 - 通过
JWTSuccessEvent的getToken()方法直接获取编码后的JWT字符串 - 增加
UserInterface类型判断,避免非用户身份场景报错
内容的提问来源于stack exchange,提问作者Casso
相关产品推荐
相关产品推荐

