fix: deduplicate expired token handling
This commit is contained in:
+28
-23
@@ -46,6 +46,22 @@ const isTokenExpiringSoon = () => {
|
||||
let isRefreshing = false
|
||||
// 等待刷新token的请求队列
|
||||
let refreshSubscribers = []
|
||||
let authRedirecting = false
|
||||
|
||||
const clearAuthAndRedirect = (message = '登录过期,请重新登录') => {
|
||||
localStorage.removeItem(TOKEN_KEY)
|
||||
localStorage.removeItem(TOKEN_EXPIRE_KEY)
|
||||
localStorage.removeItem(USER_INFO_KEY)
|
||||
onTokenRefreshed(null)
|
||||
if (authRedirecting) return
|
||||
authRedirecting = true
|
||||
ElMessage.closeAll()
|
||||
ElMessage.warning(message)
|
||||
if (router.currentRoute.value.path !== '/login') router.replace('/login')
|
||||
}
|
||||
|
||||
// 鉴权失效后终止原页面请求链,避免并发请求进入各页面 catch 后重复弹错。
|
||||
const stopExpiredRequest = () => new Promise(() => {})
|
||||
|
||||
// 添加请求到队列
|
||||
const subscribeTokenRefresh = (callback) => {
|
||||
@@ -83,20 +99,12 @@ const doRefreshToken = async () => {
|
||||
}
|
||||
}
|
||||
// 刷新失败,触发登出逻辑
|
||||
localStorage.removeItem(TOKEN_KEY)
|
||||
localStorage.removeItem(TOKEN_EXPIRE_KEY)
|
||||
localStorage.removeItem(USER_INFO_KEY)
|
||||
ElMessage.warning('登录过期,请重新登录')
|
||||
router.push('/login')
|
||||
clearAuthAndRedirect()
|
||||
return null
|
||||
} catch (error) {
|
||||
console.error('Token刷新失败:', error)
|
||||
// 刷新失败,触发登出逻辑
|
||||
localStorage.removeItem(TOKEN_KEY)
|
||||
localStorage.removeItem(TOKEN_EXPIRE_KEY)
|
||||
localStorage.removeItem(USER_INFO_KEY)
|
||||
ElMessage.warning('登录过期,请重新登录')
|
||||
router.push('/login')
|
||||
clearAuthAndRedirect()
|
||||
return null
|
||||
}
|
||||
}
|
||||
@@ -122,6 +130,10 @@ class Request {
|
||||
return config
|
||||
},
|
||||
(error) => {
|
||||
if (error.response?.status === 401) {
|
||||
clearAuthAndRedirect()
|
||||
return stopExpiredRequest()
|
||||
}
|
||||
return Promise.reject(error)
|
||||
}
|
||||
)
|
||||
@@ -206,14 +218,8 @@ http2.interceptors.request.use(async config => {
|
||||
if (urlNeedAuth(config.url)) {
|
||||
// 检查token是否已过期
|
||||
if (isTokenExpired()) {
|
||||
if (token) {
|
||||
localStorage.removeItem(TOKEN_KEY)
|
||||
localStorage.removeItem(TOKEN_EXPIRE_KEY)
|
||||
localStorage.removeItem(USER_INFO_KEY)
|
||||
ElMessage.warning('登录过期,请重新登录')
|
||||
}
|
||||
router.push('/login')
|
||||
return Promise.reject(new Error('Token已过期'))
|
||||
clearAuthAndRedirect(token ? '登录过期,请重新登录' : '请先登录')
|
||||
return stopExpiredRequest()
|
||||
}
|
||||
|
||||
// 检查token是否即将过期,进行无感刷新
|
||||
@@ -251,6 +257,7 @@ http2.interceptors.request.use(async config => {
|
||||
})
|
||||
} else {
|
||||
// 正常情况,直接使用token
|
||||
authRedirecting = false
|
||||
config.headers.Authorization = `Bearer ${token}`
|
||||
}
|
||||
}
|
||||
@@ -269,14 +276,12 @@ http2.interceptors.response.use(
|
||||
}
|
||||
const { status } = error.response;
|
||||
if (status === 401) {
|
||||
localStorage.removeItem(TOKEN_KEY);
|
||||
ElMessage.warning('登陆过期,请重新登陆')
|
||||
router.push('/login')
|
||||
return Promise.reject();
|
||||
clearAuthAndRedirect()
|
||||
return stopExpiredRequest()
|
||||
}
|
||||
// 其他错误处理(可选)
|
||||
return Promise.reject(error);
|
||||
}
|
||||
);
|
||||
|
||||
export default request
|
||||
export default request
|
||||
|
||||
Reference in New Issue
Block a user