您现在的位置是:首页 >技术杂谈 >TypeScript Axios 实现无感刷新Token网站首页技术杂谈
TypeScript Axios 实现无感刷新Token
简介axios promise刷新token 拦截
在前端开发中,无感刷新 Token 是一种常见的优化用户体验的技术。它的核心思想是:当用户的 Access Token 过期时,自动使用 Refresh Token 获取新的 Access Token,而不需要用户重新登录。以下是使用 TypeScript 和 Axios 实现无感刷新 Token 的完整方案。
1. 实现思路
- 拦截请求:使用 Axios 的请求拦截器,在每次请求时检查 Access Token 是否过期。
- 拦截响应:使用 Axios 的响应拦截器,检查响应状态码。如果 Access Token 过期(如 401 错误),则尝试使用 Refresh Token 获取新的 Access Token。
- 重试请求:在获取新的 Access Token 后,重新发送之前失败的请求。
- 避免重复刷新:在刷新 Token 的过程中,如果有多个请求同时失败,只刷新一次 Token。
2. 代码实现
实现无感刷新 Token
refresh-token.ts
import { setToken, setRefreshToken } from "./token";
let refreshTokenPromise: Promise<void> | null = null;
/**
*刷新token
*
* @export
* @return {*} {Promise<void>}
*/
export async function refreshToken(): Promise<void> {
if (refreshTokenPromise) {
return refreshTokenPromise;
}
refreshTokenPromise = new Promise<void>(async(resolve) => {
//调用刷新token接口 _isRefreshToken 标记请求是刷新token请求
const { data } = await http.get("/auth/refreshToken", { headers: { Authorization: getRefreshToken() }, _isRefreshToken: true });
//存储刷新后的token
setToken(data.token);
setRefreshToken(data.refreshToken);
resolve();
});
refreshTokenPromise.finally(() => {
refreshTokenPromise = null;
});
return refreshTokenPromise;
}
/**
*判断是否是刷新token请求
*
* @export
* @param {*} config 请求配置
* @return {boolean}
*/
export function isRefreshToken(config: any): boolean {
return !!config._isRefreshToken;
}
axios 响应拦截处理请求401 刷新token
import { refreshToken, isRefreshToken } from "./refresh-token"
import { getToken } from "./token";
import config from "@/config";
const $http = axios.create({
// 默认地址
baseURL: config.apiBasePath,
// 设置超时时间(90s)
timeout: ResultEnum.TIMEOUT as number,
// 跨域时候允许携带凭证
withCredentials: false
});
$http.interceptors.response.use(
response => {
const { data } = response;
return data;
},
async(error) => {
const { response } = error;
//token过期
if (response?.status === 401) {
//判断当前请求是否是刷新token的请求
if (!isRefreshToken(response.config)) {
await refreshToken();
//刷新token成功 用新的token重新发起请求
response.config.headers.Authorization = getToken();
return await $http.request(config);
} else {
//token刷新失败 跳转登录页
}
}
}
)
3. 关键点解析
-
响应拦截器:
- 如果响应状态码为 401(未授权),则尝试使用 Refresh Token 刷新 Access Token。
- 使用Promise的唯一性 刷新Token,待刷新完成后重新发送请求。
-
避免重复刷新:
- 判断当前请求是否是刷新Token的请求,确保同一时间只刷新一次 Token。、
- 刷新失败 (refreshToken 已过期) 跳转登录页
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。