问题
I've inherited a Symfony project that uses this controller to authenticate users:
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
]);
}
}
And the customer requests an update: token should expire 10 seconds after the login. So, following the documentation, I added this listener.
<?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);
}
}
And, of course, I've marked the listener to observe the event
acme_api.event.jwt_created_listener:
class: AppBundle\EventListener\JWTCreatedListener
tags:
- { name: kernel.event_listener, event: lexik_jwt_authentication.on_jwt_created, method: onJWTCreated }
If I get a token with Postman and use it to make following requests I can make those request for days and days. The token never expire. My JWTCreatedListener does not seem to work.
What's wrong?
回答1:
They never expire because you are using a low level api which is the JWT encoder. As you can see (since you call it), encode()
takes the payload.
For getting token expiration, the payload must contain the exp
claim with the expiration timestamp as value.
This is handled by the lexik_jwt_authentication.jwt_manager
service which uses the value of the lexik_jwt_authentication.encoder.token_ttl
config option to determine the expiration date. Set it and uses $this->get('lexik_jwt_authentication.jwt_manager')->create($user)
for creating the token, then $this->get('lexik_jwt_authentication.jwt_manager')->decode($token)
at time to decode/verify it.
Note that for using this bundle properly (allowing to hook into all the events it provides), you should consider using proper security configuration (as shown in the README) instead of doing this by hand in your controller.
回答2:
The key is here:
$token = $this->get('lexik_jwt_authentication.encoder')
->encode(['username' => $user->getUsername()]);
I need to add another parameter to encode function:
$token = $this->get('lexik_jwt_authentication.encoder')
->encode([
'username' => $user->getUsername(),
'exp' => (new \DateTime('+30 minute'))->getTimestamp(),
]);
来源:https://stackoverflow.com/questions/45914601/why-my-jwt-tokens-never-expire