fix(pda): revoke expired sessions before completing logout

This commit is contained in:
2026-10-05 13:41:34 +08:00
parent 7aebbd2a70
commit e699e9d9ba
8 changed files with 192 additions and 18 deletions
+20 -3
View File
@@ -1,8 +1,9 @@
import { refresh as refreshRequest } from '@/api/auth.js'
import { isAccessTokenExpiring, session, signOut, updateTokenPair } from '@/stores/session.js'
import { isAccessTokenExpiring, session, signOut, updateTokenPair, getSessionRevision } from '@/stores/session.js'
import { requireOnline } from '@/utils/network.js'
let refreshPromise = null
let refreshRevision = null
let redirectingToLogin = false
function responseCode(response) {
@@ -66,14 +67,21 @@ function rawRequest(options, accessToken) {
})
}
function requireSameSession(revision) {
if (getSessionRevision() !== revision) throw new Error('登录会话已变更,请重新操作')
}
async function refreshAccessToken() {
const revision = getSessionRevision()
const observedRefreshToken = session.refreshToken
if (!observedRefreshToken) return expireSession(null, observedRefreshToken)
if (!refreshPromise) {
if (!refreshPromise || refreshRevision !== revision) {
refreshRevision = revision
refreshPromise = (async () => {
if (session.refreshToken !== observedRefreshToken && session.token) return session.token
try {
const tokens = await refreshRequest(observedRefreshToken)
requireSameSession(revision)
if (session.refreshToken !== observedRefreshToken) {
if (session.token) return session.token
throw sessionExpiredError()
@@ -82,10 +90,14 @@ async function refreshAccessToken() {
redirectingToLogin = false
return session.token
} catch (error) {
requireSameSession(revision)
if (isUnauthorized(error)) return expireSession(error, observedRefreshToken)
throw error
}
})().finally(() => { refreshPromise = null })
})()
const pending = refreshPromise
const release = () => { if (refreshPromise === pending) { refreshPromise = null; refreshRevision = null } }
pending.then(release, release) // Original pending promise still propagates failures to callers.
}
return refreshPromise
}
@@ -101,12 +113,17 @@ export function ensureAccessToken() {
async function runAuthenticated(execute) {
requireOnline()
const revision = getSessionRevision()
let accessToken = await validAccessToken()
requireSameSession(revision)
let response = await execute(accessToken)
requireSameSession(revision)
if (!isUnauthorized(response)) return response
accessToken = session.token && session.token !== accessToken ? session.token : await refreshAccessToken()
requireSameSession(revision)
const activeRefreshToken = session.refreshToken
response = await execute(accessToken)
requireSameSession(revision)
if (isUnauthorized(response)) expireSession(response, activeRefreshToken)
return response
}