fix(auth): 修复登录续期令牌不同步与并发过期误判

This commit is contained in:
yml2213
2026-11-03 19:15:06 +08:00
parent 3d04175ef3
commit 0eb16c1ce2
2 changed files with 26 additions and 19 deletions
+8 -7
View File
@@ -55,12 +55,14 @@ async function request<T>(url: string, options: RequestInit = {}): Promise<T> {
const headers: Record<string, string> = {
...((options.headers as Record<string, string>) || {}),
}
// 记录本次请求实际使用的令牌,避免旧请求响应覆盖新会话。
const requestToken = token
// FormData 时不要手动设置 Content-Type,由浏览器带 boundary
const isForm = typeof FormData !== 'undefined' && options.body instanceof FormData
if (!isForm && !headers['Content-Type']) {
headers['Content-Type'] = 'application/json'
}
if (token) headers['Authorization'] = `Bearer ${token}`
if (requestToken) headers['Authorization'] = `Bearer ${requestToken}`
const res = await fetch(`${BASE}${url}`, { ...options, headers })
const nextPermissionVersion = res.headers.get('X-Permission-Version') || ''
@@ -73,17 +75,16 @@ async function request<T>(url: string, options: RequestInit = {}): Promise<T> {
}
// 服务端滑动续期:静默替换本地令牌
const renewed = res.headers.get('X-Renewed-Token')
if (renewed && renewed !== token) {
if (renewed && requestToken === token && renewed !== token) {
setToken(renewed)
tokenRenewedListener?.(renewed)
}
const json = await res.json()
if (json.code === 401) {
// 登录/续期请求本身的 401 交给调用方提示,不触发全局过期
if (!url.startsWith('/login') && !url.startsWith('/auth/refresh')) {
notifySessionExpired()
}
// 只处理当前会话令牌的 401;登录失败和已经被新令牌替换的旧请求不触发全局登出。
if ((res.status === 401 || json.code === 401) && url !== '/login' &&
requestToken !== '' && requestToken === token) {
notifySessionExpired()
}
if (json.code !== 0) {