注册
web

vue中Axios添加拦截器刷新token的实现方法

vue中Axios添加拦截器刷新token的实现方法

Axios是一款网络前端请求框架,本文主要介绍了vue中Axios添加拦截器刷新token的实现方法,

1. Axios基本用法:

        const response = await Axios.create({
           baseURL: "https://test.api.com",
           headers: {
               'Content-Type': 'application/json',
          },
        }).post<RequestResponse>('/signin', {
           user_id: "test_user",
           password: "xxx",
      });

其中,RequestResponse是返回的数据要解析为的数据类型,如下:

export interface RequestResponse {
   data: any;
   message: string;
   resultCode: number;
}

这样,得到的response就是网络请求的结果,可以进行判断处理。

2. Axios基本封装用法:

对Axios进行简单的封装,使得多个网络请求可以使用统一的header等配置。

新建一个工具类,进行封装:

import Axios, { AxiosRequestConfig, AxiosError, AxiosInstance, AxiosResponse } from 'axios';

export const BASE_URL = "https://test.api.com";

export const axiosApi = (): AxiosInstance => {
 const instance = Axios.create({
   baseURL: BASE_URL,
   headers: {
      'Content-Type': 'application/json',
      Authorization: `${getAccessToken()}`,
  },
});
   
 return instance;
}

const getAccessToken = () => {
   // 这里获取本地保存的token
   return xxxxx
}

然后使用的地方是这样:

const response = await axiosApi().post<RequestResponse>('/signin', {
    user_id: "test_user",
    password: "xxx",
});

3. 添加拦截器的用法

现在我们想再增加个功能,就是调接口时,header里传了token,但是有时候token过期了接口就会返回失败,我们想在封装的地方添加统一处理,如果token过期就刷新token,然后再调接口。

其中token的数据格式及解析方法已知如下:

import * as crypto from 'crypto';
import * as jwt from "jsonwebtoken";

export interface TokenData {
 userid: string;
 exp: number;
 iat: number;
}

export const decodeJWT = function (token: string): TokenData {
 if (!token) {
   return null;
}
 const decoded = jwt.decode(token, { complete: true });
 return decoded?.payload;
};

如何统一刷新token呢?可以添加拦截器进行处理。把对Axios的封装再改下,添加拦截器:

export const axiosApi = (): AxiosInstance => {
 const instance = Axios.create({
   baseURL: BASE_URL,
   headers: {
      'Content-Type': 'application/json',
      Authorization: `${getAccessToken()}`,
  },
});
 
 // 添加拦截器
 instance.interceptors.request.use(
   config => {
     return refreshToken(config);
  },
   err => {
     return Promise.reject(err)
  }
)
 return instance;
}

// 刷新token的方法
const refreshToken = async (config: AxiosRequestConfig) => {
 const oldToken = getAccessToken();
 if (!oldToken) { //如果本地没有token,也就是没登录,那就不用刷新token
   return config;
}

 const tokenData = decodeJWT(oldToken);//解析token,得到token里包含的过期时间信息
 const currentTimeSeconds = new Date().getTime()/1000;

 if (tokenData && tokenData.exp > currentTimeSeconds) {
   return config; // token数据里的时间比当前时间大,也就是没到过期时间,那也不用刷新
}

 // 下面是刷新token的逻辑,这里是调API获取新的token
 const response = await signInRefreshToken(tokenData?.userid);
 if (response && response.status == 200) {
   const { token, refresh_token } = response.data?.data;
   // 保存刷新后的token
   storeAccessToken(token);
   // 给API的header设置新的token
   config.headers.Authorization = token;
}
 return config;
}

经过这样添加了拦截器,如果token没过期,就直接进行网络请求;如果token过期了,那就会调接口刷新token,然后给header设置新的token再进行网络请求。

4. 注意事项:

要注意的一点是,实际应用时,要注意:

1.刷新token时如果调接口,所使用的网络请求工具不能也使用这个封装的工具,否则就会陷入无限循环,可以使用简单未封装的方式请求。

2.本例使用的方法,是进行请求前刷新token。也可以使用先调网络请求,如果接口返回错误码表示token过期,则刷新token,再重新请求的方式。

作者:程序员小徐同学
来源:juejin.cn/post/7159727466439770119

0 个评论

要回复文章请先登录注册