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
+18 -12
View File
@@ -1,6 +1,6 @@
import { createContext, useContext, useState, useCallback, useEffect, type ReactNode } from 'react'
import {
PERMISSIONS_CHANGED_EVENT, SESSION_EXPIRED_EVENT, onTokenRenewed, setToken, resetSessionExpiredFlag,
PERMISSIONS_CHANGED_EVENT, SESSION_EXPIRED_EVENT, getToken, onTokenRenewed, setToken, resetSessionExpiredFlag,
} from '@/services/request'
import {
getMe,
@@ -141,28 +141,34 @@ export function AuthProvider({ children }: { children: ReactNode }) {
}
}, [])
// 服务端滑动续期(X-Renewed-Token):同步更新内存与 localStorage 中的令牌
useEffect(() => {
return onTokenRenewed(nextToken => {
setUser(prev => {
if (!prev) return prev
const updated = { ...prev, token: nextToken }
persistUser(updated)
return updated
})
// 所有续期入口共用:同步请求模块、React 状态和 localStorage 中的令牌
const applyRenewedToken = useCallback((nextToken: string) => {
if (!nextToken) return
setToken(nextToken)
setUser(prev => {
if (!prev || prev.token === nextToken) return prev
const updated = { ...prev, token: nextToken }
persistUser(updated)
return updated
})
}, [])
// 服务端滑动续期(X-Renewed-Token)
useEffect(() => onTokenRenewed(applyRenewedToken), [applyRenewedToken])
// 定时续期:长挂机场景下每 10 分钟主动换新令牌,避免 WS 重连/请求时已过期
useEffect(() => {
if (!user?.token) return
const sessionToken = user.token
const timer = window.setInterval(() => {
void refreshSession().then(res => {
if (res.data?.token) setToken(res.data.token)
// 请求期间已退出、重新登录或由其它响应完成续期时,不再应用旧响应。
if (getToken() !== sessionToken) return
applyRenewedToken(res.data?.token || '')
}).catch(() => { /* 401 已由 request 层统一处理;网络错误等待下一轮 */ })
}, 10 * 60 * 1000)
return () => window.clearInterval(timer)
}, [user?.token])
}, [applyRenewedToken, user?.token])
// 会话过期(所有 401 的统一出口):清理登录态并回到登录页
useEffect(() => {