刷新token

This commit is contained in:
马梓彭 2026-04-03 17:49:06 +08:00
parent 2bd38e627a
commit 54bc72002c

View File

@ -14,6 +14,10 @@ export const clearAccessTokens = () => {
Session.remove(refreshAccessTokenKey);
};
// Token刷新状态和请求队列
let isRefreshing = false;
let requestQueue: Array<(token: string) => void> = [];
/**
* 检查并存储授权信息
* @param res 响应对象
@ -97,6 +101,15 @@ class Axios {
async (res: AxiosResponse) => {
// 检查并存储授权信息
checkAndStoreAuthentication(res);
// 如果正在刷新Token,且响应中包含新Token,说明刷新成功
if (isRefreshing && res.headers[accessTokenKey]) {
const newToken = res.headers[accessTokenKey];
isRefreshing = false;
requestQueue.forEach((callback) => callback(newToken));
requestQueue = [];
}
const data = res.data;
if (res.config.url?.toLocaleLowerCase() === '/file/upload'.toLowerCase()) {
return data;
@ -111,10 +124,6 @@ class Axios {
case 401:
clearAccessTokens();
message = '您已登出,请重新登录';
// ElMessageBox.alert('您已登出,请重新登录', '提示', {})
// .then(() => {})
// .catch(() => {});
// window.location.href = '/'; // 去登录页
break;
case 403:
message = '您没有权限,无法执行此项操作!';
@ -130,11 +139,54 @@ class Axios {
});
if (data.statusCode === 401) {
clearAccessTokens();
isRefreshing = false;
requestQueue = [];
window.location.href = '/'; // 去登录页
}
return Promise.reject(new Error(data.errors || 'Error'));
},
(err: any) => {
async (err: any) => {
const originalRequest = err.config;
// 如果是401错误且不是重试请求
if (err.response && err.response.status === 401 && !originalRequest._retry) {
// 如果已经在刷新Token,将请求加入队列
if (isRefreshing) {
return new Promise((resolve) => {
requestQueue.push((newToken: string) => {
originalRequest.headers['Authorization'] = `Bearer ${newToken}`;
resolve(this.instance(originalRequest));
});
});
}
// 开始刷新Token
originalRequest._retry = true;
isRefreshing = true;
// 检查是否有刷新Token
const refreshAccessToken = Session.get<string>(refreshAccessTokenKey);
if (!refreshAccessToken) {
clearAccessTokens();
isRefreshing = false;
window.location.href = '/';
return Promise.reject(err);
}
try {
// 重新发送原请求,Furion会自动处理Token刷新
originalRequest.headers['X-Authorization'] = `Bearer ${refreshAccessToken}`;
return this.instance(originalRequest);
} catch (refreshErr) {
// 刷新失败,清除所有Token并跳转登录页
clearAccessTokens();
isRefreshing = false;
requestQueue = [];
window.location.href = '/';
return Promise.reject(refreshErr);
}
}
// 这里用来处理http常见错误,进行全局提示
let message = err.message;
if (err.response && err.response.status) {
@ -144,7 +196,8 @@ class Axios {
break;
case 401:
message = '未授权,请重新登录(401)';
// 这里可以做清空storage并跳转到登录页的操作
clearAccessTokens();
window.location.href = '/';
break;
case 403:
message = '拒绝访问(403)';
@ -179,7 +232,6 @@ class Axios {
}
// 这里错误消息可以使用全局弹框展示出来
if (message) {
// 比如element plus 可以使用 ElMessage
ElMessage({
showClose: true,
message: `${message},请检查网络或联系管理员!`,