vue axios中使用accesstoken、refreshtoken实现接口保活的方案

vue axios中使用access_token、refresh_token实现接口保活的方案

回想起在做智能应用平台移动端时,通过jwt(JSON WEB TOKEN)的方式实现身份认证。简单来说就是一个加密令牌,服务端能通过算法加密用户信息并随着请求和相应传送,进而能让服务端知道登录的是谁,他有没有权限进入我的服务器获取信息。jwt有过期时间,过了这个时间,客户单再次向服务端发送接口请求的时候就需要进行重新认证,即重新登录。假如用户正在操作,这时候再次请求后端服务的时候就会突然跳到登录界面,严重影响了用户体验,智能应用平台jwt的失效时间是15min,先别说用户会有怎样的体验,就是在开发过程中,也需要反复请求新的token,简直要崩溃!还记得当时我们采用的方案是每隔一定时间,就静默地调用token请求接口,替换旧的token,这样避免用户在操作的过程中不会突然跳到登录界面的不好体验。但是,这样一来,就使得token失去了它应有的安全机制。基于当时技术的局限,只能采用这种方式。

最近看到了通过access_token、refresh_token实现token失效无痕刷新的技术博客,让我的思绪又回到了两年前那个激荡的日子。采用access_token过期,refresh_token进行刷新,很好的兼顾了用户体验和安全性的要求。基本思路如下:

  • access_token为登录后获得的请求凭证,有效期较短,例如智能应用平台为15min,使用expires(过期时间)与当前时间戳进行比较,判断是否过期,若过期,需要使用refresh_token重新获取;
  • refresh_token是用来刷新access_token的凭证,作为获取当前access_token的参数,换取新一轮的access_token,有效期一般为两倍的access_token,若过期,则需要重新登录;
  • expires是当前access_token过期时刻的时间戳,一般会在距离过期前一定时间重新请求一一轮的access_token。

刷新access_token的机制

所谓的刷新access_token就是在用户登录后会返回access_token和refresh_token两个字段,用户在访问需要权限的接口时需要带access_token字段才能进行访问,也会返回access_token的过期时间,客户端在发起每次请求时都需要检测access_token是否即将过期,如果过期了,当用户访问权限接口时就会报错而退出。为了提高用户使用时的体验感,当access_token即将过期时,客户端需要用refresh_token主要发起刷新access_token的接口来获取新的access_token。刷新成功后会返回新的access_token和refresh_token,当然了,如果refresh_token也过期了的话就只能跳到登录界面了。

刷新access_token的实现

基于axios实现该方案,axios有请求拦截器和响应拦截器,可以在请求和响应之前对请求做一些处理来实现该方案。这里有两种场景需要讨论,第一种场景是一个页面可能存在多个请求,若刚好打开页面的时候access_token过期就会有多个刷新access_token的请求;第二种场景是,一个接口刷新access_token,新的access_token还没来得及更新,另外的接口就用老的access_token去请求数据也会出错。所以,采用以下方式:

  • 当打开页面时access_token已经过期,这个页面所有请求通过数组的方式进行保存;
  • 设置一个标志判断是否正在刷新,由一个接口去请求刷新access_token,待access_token更新后,再让其他请求用心的access_token重新请求数据;

关键代码

js 复制代码
/** 是否正在刷新的标志 */
isRefreshing = false;

/** 存储请求的数组 */
let subscribers = [];

/** 将请求放入数组中 */
const addSubscribers = (cb) => subscribers.push(cb);

/** 带新的token并执行 */
const doSubscribers = (cb) => subscribers.map((cb) => cb(token));

/** axios拦截器 */
req.interceptors.request.use((request) => {
  /** 判断是否登录 */
  if (token) {
    request.headers.token = token;
    /** 判断是否即将过期,并且不是刷新token的接口refreshToken,这里是伪代码 */
    if (isExpired() && request.url !== API.refreshToken) {
      /** 先判断当前是否正在刷新,如果不是,将刷新标志置为true并请求心的token,如果是,将请求存到数组里 */
      if (!isRefreshing) {
        isRefreshing = true;
        refreshtoken().then((res) => {
          /** 新的token替换旧的token */
          request.headers.token = res.data.token;
          /** 跟新新token和refresh_token以及相关业务逻辑,这里是伪代码 */
          setData();
          /** 执行数组里的请求 */
          doSubscribers();
        })
     }
     let retry = new Promise((resolve, reject) => {
       addSubscribers((token) => {
       request.headers.token = token;
       resolve(request)
     });
  });
  return retry;
} else {
  return request;
}
} else {
  return request;
  }
}, (error) => {
  return promise.reject(error);
});

总结

使用access_token、refresh_token实现接口保活的方案不仅能够用于移动客户端,而且还能应用于采用jwt方案的鉴权系统,该方案在充分发挥jwt安全校验的基础上,还能极大的提高用户体验,并且,该方案中运用的请求队列的编程思想较为先进,对后续的开发有很好的借鉴和帮助作用。

接口数据测试

参数名称 参数位置 类型 必填 描述 示例
access_token Head String true 用户凭证,获取方式参考文档(help.hikyun.com/document/16... eyJ···9.eyJ···0.3cA···g
相关推荐
J总裁的小芒果8 分钟前
Vue3 el-table 默认选中 传入的数组
前端·javascript·elementui·typescript
Lei_zhen9611 分钟前
记录一次electron-builder报错ENOENT: no such file or directory, rename xxxx的问题
前端·javascript·electron
咖喱鱼蛋13 分钟前
Electron一些概念理解
前端·javascript·electron
yqcoder14 分钟前
Vue3 + Vite + Electron + TS 项目构建
前端·javascript·vue.js
鑫宝Code31 分钟前
【React】React Router:深入理解前端路由的工作原理
前端·react.js·前端框架
Mr_Xuhhh2 小时前
重生之我在学环境变量
linux·运维·服务器·前端·chrome·算法
永乐春秋3 小时前
WEB攻防-通用漏洞&文件上传&js验证&mime&user.ini&语言特性
前端
鸽鸽程序猿3 小时前
【前端】CSS
前端·css
ggdpzhk3 小时前
VUE:基于MVVN的前端js框架
前端·javascript·vue.js
学不会•5 小时前
css数据不固定情况下,循环加不同背景颜色
前端·javascript·html