前端token刷新并发处理

添加中间件,处理多个前端来的请求时,如果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;
       }
   }
   
原文地址:https://www.cnblogs.com/fenle/p/10666559.html