添加中间件,处理多个前端来的请求时,如果token需要刷新,先查看缓存,如果没有就在redis中做个标志位进行短期缓存,其他的请求发现缓存中的token,就不再刷新token了。这样就避免了重复刷新token的问题。
中间件代码
<?php namespace AppHttpMiddleware; use Closure; use JWTAuth; use TymonJWTAuthExceptionsJWTException; use TymonJWTAuthExceptionsTokenExpiredException; use TymonJWTAuthExceptionsTokenInvalidException; use IlluminateSupportFacadesRedis; class GetUserFromToken { public function handle($request, Closure $next) { $newToken = null; $auth = JWTAuth::parseToken(); if (! $token = $auth->setRequest($request)->getToken()) { return response()->json([ 'code' => '2', 'msg' => '无参数token', 'data' => '', ]); } try { $user = $auth->authenticate($token); if (! $user) { return response()->json([ 'code' => '2', 'msg' => '未查询到该用户信息', 'data' => '', ]); } $request->headers->set('Authorization','Bearer '.$token); } catch (TokenExpiredException $e) { try { sleep(rand(1,5)/100); $newToken = JWTAuth::refresh($token); $request->headers->set('Authorization','Bearer '.$newToken); // 给当前的请求设置性的token,以备在本次请求中需要调用用户信息 // 将旧token存储在redis中,30秒内再次请求是有效的 Redis::setex('token_blacklist:'.$token,30,$newToken); } catch (JWTException $e) { // 在黑名单的有效期,放行 if($newToken = Redis::get('token_blacklist:'.$token)){ $request->headers->set('Authorization','Bearer '.$newToken); // 给当前的请求设置性的token,以备在本次请求中需要调用用户信息 return $next($request); } // 过期用户 return response()->json([ 'code' => '2', 'msg' => '账号信息过期了,请重新登录', ]); } } catch (JWTException $e) { return response()->json([ 'code' => '2', 'msg' => '无效token', 'data' => '', ]); } $response = $next($request); if ($newToken) { $response->headers->set('Authorization', 'Bearer '.$newToken); } return $response; } }