精华内容
下载资源
问答
  • Token 刷新并发处理解决方案

    千次阅读 2020-12-03 21:02:23
    Token 进行刷新续期,我们要解决并发请求导致重复刷新 Token问题,这也是设计刷新 Token 的难点。这里我会分别介绍前端和后端各自的处理方案。 后端方案:利用 Redis 缓存 当同时发起多个请求时,第一个接口...

    对 Token 进行刷新续期,我们要解决并发请求导致重复刷新 Token 的问题,这也是设计刷新 Token 的难点。这里我会分别介绍前端和后端各自的处理方案。

    后端方案:利用 Redis 缓存

    当同时发起多个请求时,第一个接口刷新了 Token,后面的请求仍然能通过请求,且不造成 Token 重复刷新。那么,后端在用户第一次登录时,需要将生成的 Token 数据(token 和 createTime)缓存一份到 Redis 中。

    当 Token 过期时,重新生成新的 Token 数据并更新 Redis 缓存,同时在 Redis 中设置一条 Token 过渡数据并设置一个很短的过期时间(比如 30s)。如果后面的请求发现 Token 已经被刷新了,就判断 Redis 中是否存在 Token 过渡数据,存在就放行,这样同一时间的请求都可以通过。

    源码地址:https://github.com/yifanzheng/spring-security-jwt/tree/refresh-token-redis

    Token 刷新流程图

    在这里插入图片描述

    前端方案:请求拦截

    由于前端请求都是异步的,只有一个请求的时候,刷新 Token 是比较好处理的,但并发请求下刷新 Token 处理起来有点麻烦。我们需要考虑在多个请求几乎同时发起并且 Token 都失效的情况,当第一个请求进入 Token 刷新流程时,其他请求必须等待第一个请求完成 Token 刷新后再使用新 Token 进行重试。
    简单地讲,就是同一时间有多个请求且 Token 都失效,在第一个请求进行 Token 刷新时,其他请求必须处于等待状态,直到 Token 刷新完成,才能携带新 Token 进行重试。

    下面,我使用了 Angular 的请求拦截器,利用 BehaviorSubject 进行 Token 刷新状态的监听,当 Token 刷新成功,放行后面的请求进行重试。

    除此之外,前端还可以利用 Promise,将请求存进队列中后,同时返回一个 Promise,让这个 Promise 一直处于 Pending 状态(即不调用 resolve),此时这个请求就会一直等待,只要我们不执行 resolve,这个请求就会一直在等待。当刷新 Token 的请求完成后 ,我们再调用 resolve,逐个重试。

    Github 地址:https://github.com/yifanzheng/spring-security-jwt/tree/refresh-token-frontend

    Angular 代码示列

    import { Injectable } from "@angular/core";
    import {
      HttpEvent,
      HttpInterceptor,
      HttpHandler,
      HttpRequest,
      HttpErrorResponse
    } from "@angular/common/http";
    import { throwError, Observable, BehaviorSubject, of } from "rxjs";
    import { catchError, filter, finalize, take, switchMap, mergeMap } from "rxjs/operators";
    
    @Injectable()
    export class AuthInterceptor implements HttpInterceptor {
    
      private refreshTokenInProgress = false;
      private refreshTokenSubject: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
    
      intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        if (!req.headers.has("Content-Type")) {
          req = req.clone({
            headers: req.headers.set("Content-Type", "application/json")
          });
        }
        // 统一加上服务端前缀
        let url = req.url;
        if (!url.startsWith('https://') && !url.startsWith('http://')) {
          url = "./" + url;
        }
        req = req.clone({ url });
        req = this.setAuthenticationToken(req);
    
        return next.handle(req).pipe(
          mergeMap((event: any) => {
            // 若一切都正常,则后续操作
            return of(event);
          }),
          catchError((error: HttpErrorResponse) => {
            // 当是 401 错误时,表示 Token 已经过期,需要进行 Token 刷新
            if (error && error.status === 401) {
              if (this.refreshTokenInProgress) {
                // 如果 refreshTokenInProgress 为 true,我们将等到 refreshTokenSubject 是 true 时,才可以再次重试该请求
                // 这表示刷新 Token 动作已完成,新 Token 已准备就绪
                return this.refreshTokenSubject.pipe(
                  filter(result => result),
                  take(1),
                  switchMap(() => next.handle(this.setAuthenticationToken(req)))
                );
              } else {
                this.refreshTokenInProgress = true;
                // 将 refreshTokenSubject 设置为 false,以便后面的请求调用时将处于等待状态,直到检索到新 Token 为止
                this.refreshTokenSubject.next(false);
                return this.refreshToken().pipe(
                  switchMap((newToken: string) => {
                    this.refreshTokenSubject.next(true);
                    // 重新设置新的 Token
                    localStorage.setItem("token", newToken);
                    return next.handle(this.setAuthenticationToken(req));
                  }),
                  // 当刷新 Token 请求完成后,需要将 refreshTokenInProgress 设置为 false,用于下次刷新 Token
                  finalize(() => (this.refreshTokenInProgress = false))
                );
              }
            } else {
              return throwError(error);
            }
          })
        );
      }
    
      private refreshToken(): Observable<any> {
        // 这里需要换成实际的 Token 刷新接口
        return of("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJzdGFyIiwicm9sZSI6WyJST0xFX1VTRVIiXSwiaXNzIjoic2VjdXJpdHkiLCJpYXQiOjE2MDY4MjczMDAsImF1ZCI6InNlY3VyaXR5LWFsbCIsImV4cCI6MTYwNjgzNDUwMH0.Hiq2DsH6j4XFd_v87lDWGlYembTLck7DjMLRLWdyvOo");
      }
    
      private setAuthenticationToken(request: HttpRequest<any>): HttpRequest<any> {
        return request.clone({
          headers: request.headers.set("Authorization", "Bearer " + localStorage.getItem("token"))
        });
      }
    }
    
    展开全文
  • 情况说明在app开发中,我们需要保证用户登录之后,如果没有在其他设备上登录,则不需要...刷新token流程图如下:刷新token流程图.png暂时我了解的方案有两种:在获取token的时候,同时获得token的有效时间和刷新toke...

    情况说明

    在app开发中,我们需要保证用户登录之后,如果没有在其他设备上登录,则不需要再次登录,很多都会使用token作为安全令牌,开始阶段都会在登录时候获取,一直使用到下次登录。这样的token没有什么安全性可言,所以大多app都会做token时效性处理。

    刷新token流程图如下:

    0dd504933b9117f65a134734c297a347.png

    刷新token流程图.png

    暂时我了解的方案有两种:

    在获取token的时候,同时获得token的有效时间和刷新token时用的refreshToken(只允许使用一次),在请求接口的时候判断token是否在有效期内,如若在这个时间内,则继续使用旧token,不在这个时间段则根据token和RefreshToken请求token刷新接口,重新获取;并且后台也会判断token是否有效,token无效,refreshToken有效,给出错误码,可以刷新token;token无效,refreshToken无效,给出错误码,重新登录获取token。

    if ((currentTime - startTime) < validTime) {

    //使用原有的token

    } else {

    //根据refreshToken刷新token,获取新的token

    }

    登陆获取token,使用该token一直请求接口,后台判断token是否失效,如果失效抛出401错误,客户端在请求头中截取请求Code,如果是401错误,则刷新token,并用刷新获得的新token请求接口。

    public okhttp3.Response intercept(Chain chain) throws IOException {

    request = request.newBuilder()

    .header(AUTH_HEADER_KEY, BEARER_HEADER_VALUE + token)

    .build();

    Response response = chain.proceed(request);

    //判断请求接口是否发生401错误

    if (response.code() == HttpURLConnection.HTTP_UNAUTHORIZED) {

    //同步刷新token,获得newToken

    Request newRequest = request.newBuilder()

    .removeHeader(AUTH_HEADER_KEY)

    .addHeader(AUTH_HEADER_KEY, BEARER_HEADER_VALUE + newToken.getAccessToken())

    .build();

    response = chain.proceed(newRequest);

    }

    return response;

    }

    我们使用的是第一种方案,但是在开发过程中出现刷新token并发的情况

    遇问题说明

    在token失效期间,多个接口同时请求刷新token这个接口,由于refreshToken的有效性只为一次,当第一个请求接口去刷新token,当接口还没有请求成功,token还没有刷新,后面的接口请求时,token也是失效的,需要刷新。后面的其他接口在使用原来的refreshToken刷新,则会失败,接口调用错误,退回到登录页面,与当初设想的效果不符。

    对于第二种方法,没有实践过。当多个接口的token失效,一同去刷新token,后台返回来的是同一个token还是不相同,安全性可靠么,并发是怎样处理的?希望广大网友有遇到这样的情况在下方留言,在下感激不尽。

    问题解决思路

    在retrofit中个人还没有找到可以实现多个接口并发,而且同步操作的方法。往上有人说建议使用retrofit+Rxjava可以实现,但是本人对Rx才上手还没有深入了解。所以能否解决这个问题,我还不知道。我解决问题的思路如下:

    思路一

    接口几乎是同时请求,那么我在请求每个接口的时候都增加一个Thread.sleep(1000);当网络比较慢的时候效果还可以,但是当网络状态良好,问题相当于没有解决。

    思路二

    使用handler.sendMessage();使用消息队列进行处理,问题仍然没有解决

    思路三

    多线程同步,每次请求都是一个异步操作,想让获取token这个过程按照顺序来,就需要同步操作或者线程队列。这个思路解决所遇到的问题。

    多线程同步

    解决当下的问题,有三种方法:

    一是使用synchronized关键字,对方法进行同步。

    public synchronized String getToken(){

    final String token = "";

    //对token进行有效判断,有效则使用原有的;无效则对token进行刷新操作

    // :warning:刷新token的接口要使用同步操作,否则无用

    //....

    return token;

    }

    二是使用synchronized(object){}同步代码快的方法,把需要同步的操作放到“{}”内。与一是一样的

    synchronized (this){

    //需要同步的代码块

    }

    三是使用重入锁ReenreantLock实现线程同步

    private Lock mLock = new ReentrantLock();

    public String getToken(){

    mLock.lock();

    try{

    //需要上锁的代码块

    }finally{

    mLock.unlock();

    }

    }

    此时要注意及时释放锁,否则会出现死锁,通常在finally代码释放锁

    涉及知识点

    synchronized关键字是用来控制线程同步的,就是在多线程的环境下,控制synchronized代码段不被多个线程同时执行。synchronized既可以加在一段代码上,也可以加在方法上。

    ReentrantLock:官方说明是一个可重入的互斥锁定 Lock,它具有与使用 synchronized 方法和语句所访问的隐式监视器锁定相同的一些基本行为和语义,但功能更强大。ReentrantLock 将由最近成功获得锁定,并且还没有释放该锁定的线程所拥有。当锁定没有被另一个线程所拥有时,调用 lock 的线程将成功获取该锁定并返回。如果当前线程已经拥有该锁定,此方法将立即返回。可以使用 isHeldByCurrentThread() 和 getHoldCount() 方法来检查此情况是否发生。

    :warning:多线程同步操作是一种耗费资源,耗时的操作,在开发中能不使用尽量不使用。

    总结

    解决刷新token这个问题上,需要我们了解retrofit的同步异步请求,同时需要知道如何在retrofit的请求中添加header,并用多线程同步的知识进行token的获取,至少需要了解synchronized或ReentrantLock 其中一种的用法和实现。只有掌握更多的知识,才可以解决更加艰难的问题。

    参考文档

    注意:本文来自简书。本站无法对本文内容的真实性、完整性、及时性、原创性提供任何保证,请您自行验证核实并承担相关的风险与后果!

    CoLaBug.com遵循[CC BY-SA 4.0]分享并保持客观立场,本站不承担此类作品侵权行为的直接责任及连带责任。您有版权、意见、投诉等问题,请通过[eMail]联系我们处理,如需商业授权请联系原作者/原网站。

    展开全文
  • 主要介绍了vue的token刷新处理的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • 添加中间件,处理多个前端来的请求时,如果token需要刷新,先查看缓存,如果没有就在...这样就避免了重复刷新token问题。 中间件代码 <?php namespace App\Http\Middleware; use Closure; use...

    添加中间件,处理多个前端来的请求时,如果token需要刷新,先查看缓存,如果没有就在redis中做个标志位进行短期缓存,其他的请求发现缓存中的token,就不再刷新token了。这样就避免了重复刷新token的问题。

    中间件代码

       <?php
       
       namespace App\Http\Middleware;
       
       use Closure;
       use JWTAuth;
       use Tymon\JWTAuth\Exceptions\JWTException;
       use Tymon\JWTAuth\Exceptions\TokenExpiredException;
       use Tymon\JWTAuth\Exceptions\TokenInvalidException;
       use Illuminate\Support\Facades\Redis;
       
       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

    展开全文
  • 前言: 最近在尝试做前后端分离的项目,由于之前一直听过token和jwt,似乎在前后端分离中也很常用。于是便了解了一番,结果扯出一大堆问题,折腾了好久,所以想把一些问题和...token刷新策略 传统的token认证,...

    前言:

      最近在尝试做前后端分离的项目,由于之前一直听过token和jwt,似乎在前后端分离中也很常用。于是便了解了一番,结果扯出一大堆问题,折腾了好久,所以想把一些问题和思考记录一下。另外,其实前后端分离若无特殊需求,也不必执着于使用token认证,毕竟这会引发一些问题,未必就比传统cookie-session好。下面逐步讲述。

    token刷新策略

         传统的token认证,即以token为令牌(可以是一串uuid),服务端缓存下来,发给客户端。请求时根据请求携带的token来认证用户是否登陆以及取数据等。

         但是token得设置有效期,不然用户就可以一直访问了。特别是如果token被窃取后,不会过期就很麻烦。所以需要设置过期时间。

         而设置token有效期后又引发一个问题,一旦token过期,一般会要求用户重新登陆认证,用户体验差,于是人们想出了隐式地刷新token,让用户感觉不到。而隐式地刷新token,需要考虑一些问题:如果在过期的时间点,一个页面同时发起多个ajax请求过来。那么第一个请求服务端校验后发现token过期。便会刷新token。而后续的几个请求携带的仍然是旧token,就会被拒绝。如果这样,那页面上就请求不到资源了,会让人觉得很奇怪。解决办法可以参考如下几种

    • 后台解决方案:在服务端缓存或数据库中,保存两份token,一份是当前有效的token,一份是上次失效的preToken。当在过期时间点有多个请求并发访问时,检查到请求头中的token已经失效,把preToken设置为当前失效的token,把token更新为新的token。之后的其他并发访问的请求,发现它们的token和缓存中已经刷新的token不一致,就去检查是否和preToken一致,如果一致,也可以允许访问。这样一来,并发访问就没问题了。
    • 前端解决方案:前端使用axios拦截器,每次返回结果时,检查是否token过期。如果token已经过期,那么发起刷新token请求。当然,如果只是这样,上面的问题并没解决,并发访问的那几个请求由于因为token过期,会同时发起多个token刷新请求,这样会造成重复刷新token。所以,可以这样设计,前端保存一个变量isfreshing,表示当前是否正在请求刷新token。为0表示没有,则可以发起刷新token请求;为1则表示已经在请求新token,利用promise保存当前请求。如果发现token失效,就把isfreshing置为1,并发送刷新请求。这时候,如果其他并发请求也由于token失效要发起刷新token请求时,检查到isfreshing已经是1了,就不会发起请求,并且该token失效的请求被保存起来,直到新token返回后重新发起。这样的实现应该是没问题的,思路参考该文章 https://segmentfault.com/a/1190000016946316 (侵删)具体代码我还没怎么研究(Promise比较烂,所以没怎么看懂),但是应该是这个思路没错。

        以上就是两种可行的解决方案,其实后台解决方案还有其他类似的方法,比如设置一个允许过期的误差时间等。

        无论是什么方法,要注意的是该方法在刷新token的同时,要解决两个问题:1.多个请求在过期点并发访问,后面的请求不会失败。2. 不会造成多次重复刷新token问题

    jwt过期及作废问题

    jwt是一种token的实现规范,一大特点就是通过非对称加密,使得可以做到无状态token(服务端不需保存任何信息)。但是jwt的使用还是需要慎重。这里主要讲一下一个困惑我很久的问题

       作废问题:由于服务端不存储任何jwt信息,所以使得无法作废已经颁布的jwt token(比如修改密码,必须作废jwt)。这一点很致命,网上有的办法是服务端缓存一个黑名单,存储已经作废的token,其实这样就变得有状态了,需要服务端的存储。或者干脆把Jwt缓存到服务端,无论哪种方法,都破坏了jwt的无状态特性,那和普通的token,session也没有区别了其实

       过期时间问题:Jwt一般也都要设置过期时间,其实就是在payload中加一个过期时间戳,但是这样其实很不安全,payload里面的内容只是经过简单的base64加密,是可以很简单破解修改的。对于过期的token,可以简单的修改日期就可以重用了。而如果把jwt的信息和过期时间缓存在服务端,倒是可以解决问题,但是又回到了老问题——有状态jwt。

    -----综上,其实使用Jwt还是又很多问题有待思考的,并不是说它不好,jwt也有它自己适用的场景,只是用的时候要考虑好问题。虽然服务器无需缓存jwt任何信息是一大亮点,但并不是任何场景下这一点都能用好。

    关于jwt问题主要参考了如下文章(侵删)

    https://learnku.com/articles/22616

    总结

    这样看来,其实token本身也是有很多麻烦的,当然也有它的用武之地。但是传统的cookie-session机制其实也挺好的,有些人觉得对于前后端分离,app程序这些,cookie没法带上。其实倒不至于,前后端分离项目也是可以让前端请求带上cookie的,而app中也有相应的实现。至于谈到分布式,也有spring session等技术可以实现session共享。session由于存在比较久远,相应的技术还是挺全面的,这样以来,其实session机制也是挺好的(我是这么想的)。当然,具体使用情况还是看具体业务吧,各有各的用处。

    本文只是我这段时间对token学习的理解和记录(因为实在有太多疑惑。。),如果有不对的地方或疑惑的地方,欢迎提出共同讨论,彼此学习!!!

    展开全文
  • 前端解决刷新token并发请求

    千次阅读 2020-08-10 14:43:49
    解决办法:请求一次刷新token,其余刷新成功后的回调请求缓存等token刷新成功后在发起请求。 我是uiapp项目,以unapp为例,其余项目同理 1.封装请求函数,你的就是你自己的封装好的请求函数,在提示token异常需要...
  • 使用redis加锁实现,拿到锁的线程进行token刷新,拿不到锁的线程跳过token刷新 具体实现 /** * 刷新AccessToken */ private boolean refreshToken(String uid,String account, ServletResponse response) { ...
  • 避免token并发问题

    2021-07-12 16:57:59
    Redis可以用删除操作来判断Token是否有效, 删除成功代表Token校验通过,采用select+del来校验Token 会存在并发问题
  • 本篇文章主要介绍了Android OkHttp实现全局过期token自动刷新示例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • Token并发解决方案

    2021-01-05 15:57:48
    Token并发解决方案 一:作为token使用的第三方 客户端模式使用token 可以采用单例模式或定义一个全局变量isRefresh 标志,加同步锁Synchronized来保证token过期的那个时间点,刷新token方法只被调用一次。 二:...
  • 什么事并发情况下token失效:进入同一个页面,会有同时多个接口都在调用,接口调用都是异步请求,而这时候token是失效的,导致这些接口调用都是因为token失效问题,又不能因为某个接口token失效而改变token之后才去...
  • [https://www.jianshu.com/p/eb7042693d52](https://www.jianshu.com/p/eb7042693d52)
  • python 多并发竞争微信token刷新问题的解决方案
  • 背景: 后端设计token 过期时间是四个小时,但有一个用户总是挂着账号,然后就...首先并发请求 肯定不至于 每一个都需要去刷新token 只需要第一个知道过期的那个请求去刷新就可以。 这个时候需要我们怎么做呢?就是搞
  • vue axios 刷新token 刷新jwt js刷新token http刷新token

    千次阅读 热门讨论 2019-04-23 17:27:58
    前言 在互联网的登陆系统中一般有session cookie 和 jwt token来进行验证用户是否登录的.下面来说一下关于 jwt的坑: 1.首先登录成功的返回,其中jwt的有效期为2小时,refreshJwt的有效期为30天如下: 2.保存jwt 和...
  • vue的token刷新处理

    千次阅读 2020-08-25 10:22:13
    token处理登录的web系统,一般会有两个token:access-token和refresh-token。 node.js中,一般用jsonwebtoken这个模块。 access-token,是用户输入登录的账号密码,后台去db验证然后颁发的,它一般记录在浏览器的...
  • 这里说明一个使用过程中,最重要的的一个环节刷新token带来的问题。业务要达到的目标:用户登录一次之后,前端保存token,后面每次向后端请求的时候,header都带上authorization信息,后端从请求中解析token,根据...
  • 前端实现token刷新

    千次阅读 2020-06-24 10:41:09
    token是有时效的,这时候我们就需要一个刷新token的操作来保障用户的登录状态。 1. 原理 3. 完整代码 request.ts import axios, { AxiosInstance } from 'axios' import router from '@/router' import ...
  • 在业务中经常会遇到这种需求,用户登录后用户token是具有一定的时效性的,当token过期后怎样刷新token,且用户并不会感知到token已经刷新了呢,这个时候就需要我们在拦截器里面进行处理了。 实现方式:一般后台会...
  • 如果过期如何给它生成新的 token 并且考虑到高并发问题(在分布式环境下可以采用分布式锁) // TODO 给出一个实现方案,在线判断是否过期,如果过期根据 SecurityContextHolder.getContext().getAuthentication()...
  • access_token 微信文档里存在两种access_token:普通 access_token 和 网页授权 access_token。具体区别参考:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140842 以下提到的 access_token 均为...
  • 前段时间在cnode上看到一个关于微信 access_token问题:高并发如何保证微信 token 的有效。其中本人也在上面回复了一下,但是觉得解决方案还是不够好,于是就有了本篇:本文主要以渐进的方式,来一步一步解决高...
  • 依赖的包,三个包都需要 <groupId>org.quartz-scheduler ...实现定时刷新数据库内access_token的值,保证数据的准确性。 如果我的文章对你有所帮助,请扫码支持我,写出更多优秀文章!!  
  • 自动刷新token方案

    千次阅读 2018-07-24 06:00:08
    本文结合Rxjava Okhttp Retrofit 开源方案予以实现 ...多业务请求并发访问时,所有请求均失效,保证仅有一次refreshToken操作 对refreshToken进行合理的节流 业务请求+refreshToken 合理的降级策略 特殊场景...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 8,498
精华内容 3,399
关键字:

token刷新并发问题