OAuth2.0刷新Token,正在操作时,Token不过期

文件名称 版本号 作者 qq 版本
OAuth2.0刷新Token v1.0.0 学生宫布 8416837 SpringBoot 2.2.6
SpringCloud Hoxton.SR4

需求

  • 保证页面不会在正在操作中却弹出Token过期,这样体验不好。除非好久(设定的阈值)没有操作页面了,显示已过期才合理。

假设你已经搭建好OAuth2.0服务器

  • 登录(授权)成功后,响应数据长这个样子: 在这里插入图片描述
名词 释义 备注
access_token 作为消费服务的通行证,逾期会失效
refresh_token 用来换取新的access_token,会失效,但一般应该设置比access_token晚些失效
expires_in 多久过期(秒) 可在数据库设置或者在令牌管理器代码设置
  • 但如果正在操作中,令牌(通行证)突然到期失效了,那多尴尬
  • 因此需要在即将过期或已经过期的时候,刷新Token。——前提是refresh_token没有过期且合法。

解决办法

  • 前提:可以成功获取Token,并成功在客户端维护Token、过期时间

1)定时器

  • 原理 计算Token过期的时间点,开始计时,当当前时间点接近过期点的时候,执行刷新Token操作。要保证每个页面都可能触发计时器,且只能有一个,当页面刷新时,计时器不受影响。
  • 代码 节选
// 从存储获取过期时间
computed: mapGetters(['userInfo', 'isLock', 'isCollapse', 'website', 'expires_in']),
... ...
// 这里是aJax请求拦截器
// 如果即将过期,则调用刷新API,参数是refresh_token, grant_type:授权类型,即refresh_token, scope;并锁住刷新接口
          if (this.expires_in <= 1000 && !this.refreshLock) {
            this.refreshLock = true
            this.$store
              .dispatch('RefreshToken')
              .catch(() => {
                clearInterval(this.refreshTime)
              });
              
            this.refreshLock = false
          }
          // expires_in递减
          this.$store.commit("SET_EXPIRES_IN", this.expires_in - 10);
... ...

this.$store.dispatch('RefreshToken'):调用刷新 API

2)请求拦截式,每次请求权限接口都判断是否可以刷新Token了

  • 代码 节选
// 这里是aJax请求拦截器
window.isRefreshing = false
... ...
 // futureTime:Token在将来某个时间点过期
  if (!window.isRefreshing && futureTime && (futureTime - new Date().getTime() ) <= EXPIRED_IN_THIS_SECONDS ) { // 如果expires_in_time eq 0,则很可能是初次登陆,从而勿须刷新令牌 假如设置还差6秒过期
    // 锁 避免多个调用重复刷新
    window.isRefreshing = true
    // 刷新Token

如果同时调用多个接口,而此时Token已经过期,但refresh_token没有过期的话,最先刷新的接口可以执行成功,另外的接口不会刷新,会导致请求失败。但是之后会正常,因为已经刷新了。见下图:

Mon 06 Mon 13 请求1刷新中 请求路上 请求3请求中,但是木有Token 请求2 时序图

猜你喜欢

转载自blog.csdn.net/cc007cc009/article/details/106820201