前端根据refresh_token无感刷新token

690 阅读1分钟

当token失效后,需要使用refresh_token去刷新请求新的token,当刷新完请求之后,要将同一时间因为token失效而请求失败的请求再次发送。

思路:定义一个isRefreshing = false标志,当刷新请求时 isRefreshing = true

定义一个储存刷新token期间返回的401接口的数组,requestList = [],当刷新token后重新发起这些失败的请求。

const request = axios.create({
  baseURL: '',
  timeout: 10000
})
 
// 请求拦截器
request.interceptors.request.use(
  config => {
    // 统一设置用户身份 Token
    const token = 'xxx'
    if (token) {
      config.headers.Authorization = `Bearer ${token}`
    }
    return config
  },
  error => {
    return Promise.reject(error)
  }
)

 // 控制刷新token的状态
let isRereshing = false
// 存储刷新token期间过来的401请求
let requestList: any[] = []

// 响应拦截器
request.interceptors.response.use(
  response => {
    const { code, result, message } = response.data
    // 状态为2xx都会进入
    if (code === ResultEnum.SUCCESS) {
      return result
    } else {
      // 做其他错误响应
      ElMessage.error(`错误信息: ${message as string}`)
      return Promise.reject(response.data)
    }
  },
  async (err) => {
    // 超出2状态码的进入这里
 
    if (err.response) {
      // 请求发出并收到响应
      const { status } = err.response
      if (status === 400) {
        ElMessage.error('请求参数错误')
      } else if (status === 401) {
        // 判断是否登录,没有登录的401直接返回到登录页面
        const usertore = useUserStore()
        if (!usertore.userInfo.id) {
          redirectLogin()
          return Promise.reject(err)
        }
 
        // 已登录, token过期 刷新token
        if (!isRereshing) {
          isRereshing = true
          return axios.post(url,{ refreshToken: usertore.userInfo?.refreshToken ?? '' }).then(res => {
            if (res.data.code !== '0000') {
              throw new Error('刷新 Token 失败')
            }
            // 刷新成功
            usertore.userInfo.token = res.data.data.token
            usertore.userInfo.refreshToken = res.data.data.refreskToken
            requestList.forEach(cb => cb())
            requestList = []
            return request(err.config)
          }).catch(e => {
            usertore.userInfo = {
              id: '',
              userName: '',
              roleId: '',
              roleName: ''
            }
            redirectLogin()
            return Promise.reject(e)
          }).finally(() => {
            isRereshing = false
          })
        }
 
        // 正在刷新中
        return new Promise(resolve => {
          requestList.push(() => {
            resolve(request(err.config))
          })
        })
      } else if (status === 403) {
        ElMessage.error('没有权限,请联系管理员')
      } else if (status === 404) {
        ElMessage.error('请求的资源不存在')
      } else if (status > 500) {
        ElMessage.error('服务端错误,请联系管理员')
      } else {
        ElMessage.error('请求失败')
      }
    } else if (err.request) {
      ElMessage.error('请求超时,请刷新重试')
    } else {
      ElMessage.error('请求失败')
    }
    return Promise.reject(err)
  }
)