feat(auth): 登录态改为滑动续期(后台 24h/7d,打手 7d/30d)

This commit is contained in:
yml2213
2026-10-25 13:28:58 +08:00
parent 81edf530db
commit 2fb7aae13f
31 changed files with 510 additions and 64 deletions
+36 -3
View File
@@ -1,7 +1,7 @@
import axios from 'axios'
import { clearAdminSession, getAdminToken } from '@/utils/admin-auth'
import { expireAdminSession, getAdminToken, setAdminSessionExpiresAt } from '@/utils/admin-auth'
import { isWorkerSite } from '@/utils/site'
import { expireWorkerSession, getWorkerToken } from '@/utils/worker-auth'
import { expireWorkerSession, getWorkerToken, setWorkerSessionExpiresAt } from '@/utils/worker-auth'
export interface ApiEnvelope<T> {
code: number
@@ -20,6 +20,7 @@ const http = axios.create({
http.interceptors.response.use(
(response) => {
applySessionExpiryHeaders(response)
const data = response.data as ApiEnvelope<unknown>
// Business-level error: HTTP 200 but code !== 0
@@ -36,6 +37,7 @@ http.interceptors.response.use(
return response.data
},
(error) => {
applySessionExpiryHeaders(error?.response)
const responseMessage =
typeof error?.response?.data?.msg === 'string' ? error.response.data.msg.trim() : ''
const fallbackMessage = resolveFallbackHttpMessage(error)
@@ -57,7 +59,7 @@ http.interceptors.response.use(
const errorCode = String(error?.response?.data?.errorCode || '').trim()
if (status === 401 && shouldClearAdminSession(errorCode)) {
clearAdminSession()
expireAdminSession()
if (
window.location.hash.startsWith('#/admin') &&
@@ -105,6 +107,37 @@ http.interceptors.request.use((config) => {
return config
})
/**
* 服务端每次校验会话都会回传滑动续期后的空闲到期时间;
* 这里同步到 localStorage,WorkerLayout / AdminLayout 的定时器会自动重排。
*/
function applySessionExpiryHeaders(
response:
| {
config?: { url?: string }
headers?: Record<string, unknown> & { get?: (name: string) => unknown }
}
| undefined,
) {
if (!response) return
const url = String(response.config?.url || '')
if (!url.startsWith('/api/v1/admin') && !url.startsWith('/api/v1/worker')) return
const headers = response.headers
const raw =
typeof headers?.get === 'function'
? headers.get('x-session-expires-at')
: headers?.['x-session-expires-at']
const expiresAt = String(raw || '').trim()
if (!expiresAt) return
if (url.startsWith('/api/v1/admin')) {
setAdminSessionExpiresAt(expiresAt)
} else {
setWorkerSessionExpiresAt(expiresAt)
}
}
function resolveFallbackHttpMessage(error: unknown) {
const message = String((error as { message?: string })?.message ?? '')