为什么我的 jwt 令牌永不过期?
Why my jwt tokens never expire?
我继承了一个使用此控制器对用户进行身份验证的 Symfony 项目:
class TokenController extends FOSRestController
{
public function postTokensAction(Request $request)
{
$username = $request->request->get('username');
$password = $request->request->get('password');
$user = $this->get('fos_user.user_manager')
->findUserByUsername($username);
if (!$user) {
throw $this->createNotFoundException();
}
$passwordEncoder = $this->get('security.password_encoder');
if(!$passwordEncoder->isPasswordValid($user, $password)) {
throw $this->createAccessDeniedException();
}
$groups = ['foo', 'bar'];
$context = SerializationContext::create()
->setGroups($groups);
$token = $this->get('lexik_jwt_authentication.encoder')
->encode(['username' => $user->getUsername()]);
$user = $this->get('jms_serializer')
->toArray($user, $context);
return new JsonResponse([
'token' => $token,
'user' => $user
]);
}
}
并且客户请求更新:令牌应在登录后 10 秒后过期。所以,按照文档,我添加了这个监听器。
<?php
namespace AppBundle\EventListener;
use Lexik\Bundle\JWTAuthenticationBundle\Event\JWTCreatedEvent;
class JWTCreatedListener
{
public function onJWTCreated(JWTCreatedEvent $event)
{
$expiration = new \DateTime('now');
$expiration->add(new \DateInterval('PT10S'));
$payload = $event->getData();
$payload['exp'] = $expiration->getTimestamp();
$event->setData($payload);
}
}
当然,我已经标记了监听器来观察事件
acme_api.event.jwt_created_listener:
class: AppBundle\EventListener\JWTCreatedListener
tags:
- { name: kernel.event_listener, event: lexik_jwt_authentication.on_jwt_created, method: onJWTCreated }
如果我通过 Postman 获得令牌并使用它来发出以下请求,我可以连续几天发出这些请求。令牌永不过期。我的 JWTCreatedListener 似乎不起作用。
怎么了?
它们永远不会过期,因为您使用的是低级别 api,即 JWT 编码器。如您所见(自您调用以来),encode()
获取有效负载。
要获取令牌过期时间,有效负载必须包含 exp
声明,并将过期时间戳作为值。
这是由 lexik_jwt_authentication.jwt_manager
服务处理的,该服务使用 lexik_jwt_authentication.encoder.token_ttl
配置选项的值来确定到期日期。设置它并使用 $this->get('lexik_jwt_authentication.jwt_manager')->create($user)
创建令牌,然后 $this->get('lexik_jwt_authentication.jwt_manager')->decode($token)
到 decode/verify 它。
请注意,为了正确使用此包(允许连接到它提供的所有事件),您应该考虑使用适当的安全配置(如 README 中所示),而不是在您的控制器中手动执行此操作。
关键在这里:
$token = $this->get('lexik_jwt_authentication.encoder')
->encode(['username' => $user->getUsername()]);
我需要添加另一个参数来编码函数:
$token = $this->get('lexik_jwt_authentication.encoder')
->encode([
'username' => $user->getUsername(),
'exp' => (new \DateTime('+30 minute'))->getTimestamp(),
]);
我继承了一个使用此控制器对用户进行身份验证的 Symfony 项目:
class TokenController extends FOSRestController
{
public function postTokensAction(Request $request)
{
$username = $request->request->get('username');
$password = $request->request->get('password');
$user = $this->get('fos_user.user_manager')
->findUserByUsername($username);
if (!$user) {
throw $this->createNotFoundException();
}
$passwordEncoder = $this->get('security.password_encoder');
if(!$passwordEncoder->isPasswordValid($user, $password)) {
throw $this->createAccessDeniedException();
}
$groups = ['foo', 'bar'];
$context = SerializationContext::create()
->setGroups($groups);
$token = $this->get('lexik_jwt_authentication.encoder')
->encode(['username' => $user->getUsername()]);
$user = $this->get('jms_serializer')
->toArray($user, $context);
return new JsonResponse([
'token' => $token,
'user' => $user
]);
}
}
并且客户请求更新:令牌应在登录后 10 秒后过期。所以,按照文档,我添加了这个监听器。
<?php
namespace AppBundle\EventListener;
use Lexik\Bundle\JWTAuthenticationBundle\Event\JWTCreatedEvent;
class JWTCreatedListener
{
public function onJWTCreated(JWTCreatedEvent $event)
{
$expiration = new \DateTime('now');
$expiration->add(new \DateInterval('PT10S'));
$payload = $event->getData();
$payload['exp'] = $expiration->getTimestamp();
$event->setData($payload);
}
}
当然,我已经标记了监听器来观察事件
acme_api.event.jwt_created_listener:
class: AppBundle\EventListener\JWTCreatedListener
tags:
- { name: kernel.event_listener, event: lexik_jwt_authentication.on_jwt_created, method: onJWTCreated }
如果我通过 Postman 获得令牌并使用它来发出以下请求,我可以连续几天发出这些请求。令牌永不过期。我的 JWTCreatedListener 似乎不起作用。
怎么了?
它们永远不会过期,因为您使用的是低级别 api,即 JWT 编码器。如您所见(自您调用以来),encode()
获取有效负载。
要获取令牌过期时间,有效负载必须包含 exp
声明,并将过期时间戳作为值。
这是由 lexik_jwt_authentication.jwt_manager
服务处理的,该服务使用 lexik_jwt_authentication.encoder.token_ttl
配置选项的值来确定到期日期。设置它并使用 $this->get('lexik_jwt_authentication.jwt_manager')->create($user)
创建令牌,然后 $this->get('lexik_jwt_authentication.jwt_manager')->decode($token)
到 decode/verify 它。
请注意,为了正确使用此包(允许连接到它提供的所有事件),您应该考虑使用适当的安全配置(如 README 中所示),而不是在您的控制器中手动执行此操作。
关键在这里:
$token = $this->get('lexik_jwt_authentication.encoder')
->encode(['username' => $user->getUsername()]);
我需要添加另一个参数来编码函数:
$token = $this->get('lexik_jwt_authentication.encoder')
->encode([
'username' => $user->getUsername(),
'exp' => (new \DateTime('+30 minute'))->getTimestamp(),
]);