mirror of
https://github.com/KwiTsukasa/kt-template-online-playground.git
synced 2026-05-27 16:45:45 +08:00
fix(playground): 修复 401 鉴权恢复跳转
This commit is contained in:
parent
e28c425603
commit
d1812d3c3d
@ -17,6 +17,7 @@ const ACCESS_CODES_KEY = 'kt-admin-access-codes'
|
||||
const USER_INFO_KEY = 'kt-admin-user-info'
|
||||
|
||||
let refreshPromise: Promise<string | null> | null = null
|
||||
let redirectingToAdminLogin = false
|
||||
|
||||
function getApiBase() {
|
||||
return import.meta.env.VITE_APP_API_BASE || '/api'
|
||||
@ -76,6 +77,9 @@ function buildAdminLoginUrl(redirect: string) {
|
||||
}
|
||||
|
||||
export function redirectToAdminLogin() {
|
||||
if (redirectingToAdminLogin) return
|
||||
|
||||
redirectingToAdminLogin = true
|
||||
window.location.href = buildAdminLoginUrl(window.location.href)
|
||||
}
|
||||
|
||||
|
||||
@ -8,10 +8,19 @@ import {
|
||||
|
||||
export type ApiResponse<T = unknown> = {
|
||||
code: number
|
||||
message?: string
|
||||
msg: string
|
||||
data: T
|
||||
}
|
||||
|
||||
type AuthRetryConfig = AxiosRequestConfig & {
|
||||
_authRetried?: boolean
|
||||
}
|
||||
|
||||
type AuthHeaderMap = Record<string, unknown> & {
|
||||
get?: (name: string) => unknown
|
||||
}
|
||||
|
||||
const request = axios.create({
|
||||
baseURL: import.meta.env.VITE_APP_API_BASE || '/api',
|
||||
timeout: 1000 * 30,
|
||||
@ -40,14 +49,61 @@ request.interceptors.request.use(async (config) => {
|
||||
return config
|
||||
})
|
||||
|
||||
function getAuthErrorMessage(data?: Partial<ApiResponse>) {
|
||||
return data?.msg || data?.message || '登录已过期'
|
||||
}
|
||||
|
||||
function getRequestAuthorization(config?: AuthRetryConfig) {
|
||||
const headers = config?.headers as AuthHeaderMap | undefined
|
||||
|
||||
if (!headers) return null
|
||||
if (typeof headers.get === 'function') {
|
||||
return headers.get('Authorization') || headers.get('authorization')
|
||||
}
|
||||
|
||||
return headers.Authorization || headers.authorization
|
||||
}
|
||||
|
||||
async function retryRequestWithFreshToken(config?: AuthRetryConfig) {
|
||||
if (!config || config._authRetried) return null
|
||||
|
||||
const hasOldAccessToken = Boolean(
|
||||
getStoredAccessToken() || getRequestAuthorization(config),
|
||||
)
|
||||
if (!hasOldAccessToken) return null
|
||||
|
||||
config._authRetried = true
|
||||
clearPersistedAuth()
|
||||
const accessToken = await refreshPersistedAuth()
|
||||
|
||||
if (!accessToken) return null
|
||||
|
||||
config.headers = {
|
||||
...(config.headers || {}),
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
}
|
||||
|
||||
// 只有旧 accessToken 过期时才尝试刷新并重放一次,未登录 401 直接去 Admin。
|
||||
return request.request(config)
|
||||
}
|
||||
|
||||
function redirectAfterAuthExpired() {
|
||||
clearPersistedAuth()
|
||||
redirectToAdminLogin()
|
||||
}
|
||||
|
||||
request.interceptors.response.use(
|
||||
(response) => {
|
||||
async (response) => {
|
||||
const data = response.data as ApiResponse<any>
|
||||
|
||||
if (response.status === 401 || data.code === 401) {
|
||||
clearPersistedAuth()
|
||||
redirectToAdminLogin()
|
||||
return Promise.reject(new Error(data.msg || '登录已过期'))
|
||||
const retryResponse = await retryRequestWithFreshToken(
|
||||
response.config as AuthRetryConfig,
|
||||
)
|
||||
if (retryResponse) return retryResponse
|
||||
|
||||
redirectAfterAuthExpired()
|
||||
return Promise.reject(new Error(getAuthErrorMessage(data)))
|
||||
}
|
||||
|
||||
if (data.code !== 200) {
|
||||
@ -56,15 +112,24 @@ request.interceptors.response.use(
|
||||
|
||||
return data.data as any
|
||||
},
|
||||
(error) => {
|
||||
async (error) => {
|
||||
if (axios.isAxiosError<ApiResponse>(error)) {
|
||||
if (error.response?.status === 401) {
|
||||
clearPersistedAuth()
|
||||
redirectToAdminLogin()
|
||||
const retryResponse = await retryRequestWithFreshToken(
|
||||
error.config as AuthRetryConfig | undefined,
|
||||
)
|
||||
if (retryResponse) return retryResponse
|
||||
|
||||
redirectAfterAuthExpired()
|
||||
}
|
||||
|
||||
return Promise.reject(
|
||||
new Error(error.response?.data?.msg || error.message || '请求失败'),
|
||||
new Error(
|
||||
error.response?.data?.msg ||
|
||||
error.response?.data?.message ||
|
||||
error.message ||
|
||||
'请求失败',
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user