Symfony JWT 令牌:令牌过期时出现异常
Symfony JWT token: exception when token is expired
我正在使用 JWT 令牌包进行用户身份验证。当令牌过期时,我收到 500 服务器错误。取而代之的是,我如何 return 带有错误代码和消息的 JsonResponse?
这是我的身份验证器 class:
class JwtTokenAuthentication extends AbstractGuardAuthenticator
{
/**
* @var JWTEncoderInterface
*/
private $jwtEncoder;
/**
* @var EntityManager
*/
private $em;
public function __construct(JWTEncoderInterface $jwtEncoder, EntityManager $em)
{
$this->jwtEncoder = $jwtEncoder;
$this->em = $em;
}
public function getCredentials(Request $request)
{
$extractor = new AuthorizationHeaderTokenExtractor(
'Bearer',
'Authorization'
);
$token = $extractor->extract($request);
if (!$token) {
return null;
}
return $token;
}
public function getUser($credentials, UserProviderInterface $userProvider)
{
$data = $this->jwtEncoder->decode($credentials);
if(!$data){
return null;
}
$user = $this->em->getRepository("AlumnetCoreBundle:User")->find($data["email"]);
return $user;
}
public function checkCredentials($credentials, UserInterface $user)
{
return true;
}
public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
{
//todo
}
public function start(Request $request, AuthenticationException $authException = null)
{
return new JsonResponse([
'errorMessage' => 'auth required'
], Response::HTTP_UNAUTHORIZED);
}
}
您可以在 try-catch 中解码令牌:
try {
$data = $this->jwtEncoder->decode($credentials);
} catch (\Exception $e) {
throw new \Symfony\Component\Security\Core\Exception\BadCredentialsException($e->getMessage(), 0, $e);
}
但是您可能必须实现缺少的 onAuthenticationFailure
,因为抛出此异常会调用它。类似于:
public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
{
return new JsonResponse([
'errorMessage' => $exception->getMessage(),
], Response::HTTP_UNAUTHORIZED);
}
顺便说一句,LexikJWTAuthenticationBundle 自 2.0 版本以来就带有一个内置 JWTTokenAuthenticator
。我建议您在实现自己的身份验证器之前尝试使用它,或者至少 extend it.
我将整个代码放在一个 try catch 块中,当生成 JWT 令牌已过期错误消息时,它会在 catch
块中被捕获。
{
"error": 1,
"status": 400,
"msg": "Expired JWT Token",
"data": []
}
/**
* @Route("/api/tokens")
* @Method("POST")
*/
public function newTokenAction(Request $request)
{
try {
$data['_username'] = $request->get('_username');
$data['_password'] = $request->get('_password');
if (empty($data['_username']) || empty($data['_password'])) {
throw new \Exception('Username or password fields empty');
}
$user = $this->getDoctrine()->getRepository('AppBundle:User')->findOneBy(array('username' => $data['_username']));
if (!$user) {
throw new \Exception('Username or password does not exist');
} else if ($user->hasRole('ROLE_SUPER_ADMIN')) {
throw new \Exception('Admin is not allowed to login through app');
} else if (!$user->getEnabled()) {
throw new \Exception('User is not enabled');
} else if ($user->getIsDeleted()) {
throw new \Exception('User does not exist any more');
}
$isValid = $this->get('security.password_encoder')->isPasswordValid($user, $data['_password']);
if (!$isValid) {
throw new \Exception('Bad Credentials');
}
$token = $this->get('lexik_jwt_authentication.encoder')->encode(array(
'username' => $data['_username'],
'exp' => time() + 3600,
'secret_key' => ____________,
));
$user->setAuthToken($token);
$em = $this->getEntityManager();
$em->persist($user);
$em->flush();
$json = $this->getJsonResponse(0, 200, 'User Logged In');
$response = new Response($json);
$response->headers->set('Content-Type', 'application/json');
return $response;
} catch (\Exception $e) {
// Using custom Execption class
$customApiProblem = new CustomApiProblem(self::API_ERROR_TRUE, $httpStatusCode, $e->getMessage());
$customApiProblem->set('data', $data);
$serializer = $this->container->get('jms_serializer');
$response_json = $serializer->serialize($customApiProblem->toArray(), 'json');
return new Response($response_json, $statusCode);
}
}
我正在使用 JWT 令牌包进行用户身份验证。当令牌过期时,我收到 500 服务器错误。取而代之的是,我如何 return 带有错误代码和消息的 JsonResponse?
这是我的身份验证器 class:
class JwtTokenAuthentication extends AbstractGuardAuthenticator
{
/**
* @var JWTEncoderInterface
*/
private $jwtEncoder;
/**
* @var EntityManager
*/
private $em;
public function __construct(JWTEncoderInterface $jwtEncoder, EntityManager $em)
{
$this->jwtEncoder = $jwtEncoder;
$this->em = $em;
}
public function getCredentials(Request $request)
{
$extractor = new AuthorizationHeaderTokenExtractor(
'Bearer',
'Authorization'
);
$token = $extractor->extract($request);
if (!$token) {
return null;
}
return $token;
}
public function getUser($credentials, UserProviderInterface $userProvider)
{
$data = $this->jwtEncoder->decode($credentials);
if(!$data){
return null;
}
$user = $this->em->getRepository("AlumnetCoreBundle:User")->find($data["email"]);
return $user;
}
public function checkCredentials($credentials, UserInterface $user)
{
return true;
}
public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
{
//todo
}
public function start(Request $request, AuthenticationException $authException = null)
{
return new JsonResponse([
'errorMessage' => 'auth required'
], Response::HTTP_UNAUTHORIZED);
}
}
您可以在 try-catch 中解码令牌:
try {
$data = $this->jwtEncoder->decode($credentials);
} catch (\Exception $e) {
throw new \Symfony\Component\Security\Core\Exception\BadCredentialsException($e->getMessage(), 0, $e);
}
但是您可能必须实现缺少的 onAuthenticationFailure
,因为抛出此异常会调用它。类似于:
public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
{
return new JsonResponse([
'errorMessage' => $exception->getMessage(),
], Response::HTTP_UNAUTHORIZED);
}
顺便说一句,LexikJWTAuthenticationBundle 自 2.0 版本以来就带有一个内置 JWTTokenAuthenticator
。我建议您在实现自己的身份验证器之前尝试使用它,或者至少 extend it.
我将整个代码放在一个 try catch 块中,当生成 JWT 令牌已过期错误消息时,它会在 catch
块中被捕获。
{ "error": 1, "status": 400, "msg": "Expired JWT Token", "data": [] }
/**
* @Route("/api/tokens")
* @Method("POST")
*/
public function newTokenAction(Request $request)
{
try {
$data['_username'] = $request->get('_username');
$data['_password'] = $request->get('_password');
if (empty($data['_username']) || empty($data['_password'])) {
throw new \Exception('Username or password fields empty');
}
$user = $this->getDoctrine()->getRepository('AppBundle:User')->findOneBy(array('username' => $data['_username']));
if (!$user) {
throw new \Exception('Username or password does not exist');
} else if ($user->hasRole('ROLE_SUPER_ADMIN')) {
throw new \Exception('Admin is not allowed to login through app');
} else if (!$user->getEnabled()) {
throw new \Exception('User is not enabled');
} else if ($user->getIsDeleted()) {
throw new \Exception('User does not exist any more');
}
$isValid = $this->get('security.password_encoder')->isPasswordValid($user, $data['_password']);
if (!$isValid) {
throw new \Exception('Bad Credentials');
}
$token = $this->get('lexik_jwt_authentication.encoder')->encode(array(
'username' => $data['_username'],
'exp' => time() + 3600,
'secret_key' => ____________,
));
$user->setAuthToken($token);
$em = $this->getEntityManager();
$em->persist($user);
$em->flush();
$json = $this->getJsonResponse(0, 200, 'User Logged In');
$response = new Response($json);
$response->headers->set('Content-Type', 'application/json');
return $response;
} catch (\Exception $e) {
// Using custom Execption class
$customApiProblem = new CustomApiProblem(self::API_ERROR_TRUE, $httpStatusCode, $e->getMessage());
$customApiProblem->set('data', $data);
$serializer = $this->container->get('jms_serializer');
$response_json = $serializer->serialize($customApiProblem->toArray(), 'json');
return new Response($response_json, $statusCode);
}
}