用axios封装无感刷新token

1. 封装接口请求

request.js

import axios from 'axios'
import { apiUrl } from '@/config/global_config'
import refreshToken from './refreshToken'

//前缀
const service = axios.create({
  baseURL: apiUrl,
  timeout: 5000 // 请求超时时间
})

//请求
service.interceptors.request.use(
  config => {
    return config
  },
  error => {
    console.log(error)
    return Promise.reject(error)
  }
)

//响应
service.interceptors.response.use(
  response => {
    const data = response.data
    if (data.code === 200) {
      return Promise.resolve(data)
    } if (data.code === 401) {
      refreshToken(response)
    } else {
      let err = {}
      let messInfo = data.message ? err.info + ' ' + data.message : err.info
      return Promise.reject(new Error(messInfo || 'Error'))
    }
  },
  err => {
    console.log('响应错误:' + err)
    return Promise.reject(err) //请求错误时,直接结束
  }
)

// 封装通用的接口调用方法
export default (options) => {
  return service({
    method: options.method || 'GET',
    url: options.url,
    // ES6规则:对象的key可以是动态的变量
    [options.method.toUpperCase() === 'GET' ? 'params' : 'data']: options.data
  })
}

2.分离刷新token的js

refreshToken.js

import { useRouter } from 'vue-router';
import request from './request';
import { ElMessage } from 'element-plus'

const MAX_ERROR_COUNT = 5; //最大请球次数
let currentCount = 0; //当前请求了多少次
const queue = []; //把阻塞的请求储存到数组里一次请求玩
let isRefresh = false;

const { router } = useRouter()
export default async function refreshToken(error) {
  // 退出登录
  const logout = () => {
    ElMessage.error('身份过期,请重新登录')

    router.replace('/login')
    // 清空数据 token的数据  
    // Session.clear();
    localStorage.clear()

    return Promise.reject(error);
  };
  if (error.config.url?.includes('refresh')) {
    // 如果url中包含refresh 退出登录
    logout();
  }
  const refresh = localStorage.getItem('refresh') ?? null;

  const { config } = error;
  if (!refresh) {  //如果没找到替换的refreshtoken退出登录
    logout();
  }
  // 判断当前是否为刷新状态中(防止多个请求导致多次调refresh接口)
  if (!isRefresh) {
    // 设置当前状态为刷新中
    isRefresh = true;
    // 如果重发次数超过,直接退出登录
    if (currentCount > MAX_ERROR_COUNT) {
      logout();
    }
    // 增加重试次数
    currentCount += 1;

    try {
      const {
        data: { access },
      } = await UserAuthApi.refreshToken(refresh);  //用refreshToken刷新token

      localStorage.setItem('token', access)   //把新token存到本地
      // 重置重发次数
      currentCount = 0;
      // 遍历队列,重新发起请求
      queue.forEach((cb) => cb(access));//用新token吧阻塞的接口全部重新请求
      // 返回请求数据
      return request(error.config);
    } catch {
     // 刷新token失败,直接退出登录
      ElMessage.error('请重新登录')
      localStorage.clear()

      router.replace('/login')
      return Promise.reject(error);
    } finally {
       // 重置状态
      isRefresh = false;
    }
  } else {
    // 当前正在尝试刷新token,先返回一个promise阻塞请求并推进请求列表中
    return new Promise((resolve) => {
      // 缓存网络请求,等token刷新后直接执行
      queue.push((newToken) => {
        Reflect.set(config.headers, 'authorization', newToken);
        resolve(request(config));
      });
    });
  }
}```

  • 9
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
刷新token是指在前端发起请求时,如果当前的token已过期,则自动刷新token,并重新发起请求,达到用户无知的效果。在axios中,可以通过拦截器实现无刷新token的功能。 在axios中,我们可以通过使用请求拦截器和响应拦截器来实现无刷新token的逻辑。首先,我们可以在请求拦截器中判断当前的token是否已过期。如果token未过期,则直接返回请求对象,如果token已过期,则在请求拦截器中发起刷新token的请求。 在刷新token的请求中,我们可以使用当前过期的token去请求后端接口,然后根据后端返回的结果来判断是否成功刷新token。如果刷新token成功,则将新的token更新到请求头信息中,并重新发起之前的请求。 在响应拦截器中,我们可以判断后端返回的响应状态码。如果响应状态码为401,说明当前的token已过期,则调用刷新token的逻辑重新获取token,并再次发起请求。如果刷新token的请求失败,则说明用户的登录状态无效,可以跳转到登录页面重新登录。 通过以上的逻辑,我们可以实现无刷新token的效果,用户不需要手动处理token过期的问题,从而提升用户体验。同时在后端也需要配合实现刷新token的逻辑,并提供相应的接口供前端调用。 无刷新token的实现涉及到了前后端的配合,前端通过axios拦截器实现token的自动刷新,后端提供相关的接口。通过这种方式,可以有效解决token过期后需要重新登录的问题,提升应用的用户体验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值