mirror of
https://github.com/KwiTsukasa/kt-template-online-web.git
synced 2026-05-27 16:35:47 +08:00
fix(web): 修复 401 鉴权恢复跳转
This commit is contained in:
parent
99f5615144
commit
c54a7f4f36
@ -18,6 +18,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;
|
||||
|
||||
const authClient = axios.create({
|
||||
baseURL: config.axiosBase,
|
||||
@ -66,6 +67,9 @@ const buildAdminLoginUrl = (redirect: string) => {
|
||||
};
|
||||
|
||||
export const redirectToAdminLogin = () => {
|
||||
if (redirectingToAdminLogin) return;
|
||||
|
||||
redirectingToAdminLogin = true;
|
||||
window.location.href = buildAdminLoginUrl(window.location.href);
|
||||
};
|
||||
|
||||
|
||||
@ -10,9 +10,18 @@ import {
|
||||
export interface ApiResponse<T = any> {
|
||||
code: number;
|
||||
data: T;
|
||||
message?: string;
|
||||
msg: string;
|
||||
}
|
||||
|
||||
type AuthRetryConfig = AxiosRequestConfig & {
|
||||
_authRetried?: boolean;
|
||||
};
|
||||
|
||||
type AuthHeaderMap = Record<string, unknown> & {
|
||||
get?: (name: string) => unknown;
|
||||
};
|
||||
|
||||
const request = axios.create({
|
||||
baseURL: config.axiosBase,
|
||||
timeout: 1000 * 30,
|
||||
@ -27,6 +36,49 @@ export const post = <T = any>(url: string, data?: any, config?: AxiosRequestConf
|
||||
return request.post<any, ApiResponse<T>>(url, data, config);
|
||||
};
|
||||
|
||||
const getAuthErrorMessage = (data?: Partial<ApiResponse>) => {
|
||||
return data?.msg || data?.message || "登录已过期";
|
||||
};
|
||||
|
||||
const getRequestAuthorization = (requestConfig?: AuthRetryConfig) => {
|
||||
const headers = requestConfig?.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;
|
||||
};
|
||||
|
||||
const retryRequestWithFreshToken = async (requestConfig?: AuthRetryConfig) => {
|
||||
if (!requestConfig || requestConfig._authRetried) return null;
|
||||
|
||||
const hasOldAccessToken = Boolean(
|
||||
getStoredAccessToken() || getRequestAuthorization(requestConfig),
|
||||
);
|
||||
if (!hasOldAccessToken) return null;
|
||||
|
||||
requestConfig._authRetried = true;
|
||||
clearPersistedAuth();
|
||||
const accessToken = await refreshPersistedAuth();
|
||||
|
||||
if (!accessToken) return null;
|
||||
|
||||
requestConfig.headers = {
|
||||
...(requestConfig.headers || {}),
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
};
|
||||
|
||||
// 只有旧 accessToken 过期时才尝试刷新并重放一次,未登录 401 直接去 Admin。
|
||||
return request.request(requestConfig);
|
||||
};
|
||||
|
||||
const redirectAfterAuthExpired = () => {
|
||||
clearPersistedAuth();
|
||||
redirectToAdminLogin();
|
||||
};
|
||||
|
||||
request.interceptors.request.use(async (requestConfig) => {
|
||||
let accessToken = getStoredAccessToken();
|
||||
|
||||
@ -42,19 +94,25 @@ request.interceptors.request.use(async (requestConfig) => {
|
||||
});
|
||||
|
||||
request.interceptors.response.use(
|
||||
(response) => {
|
||||
async (response) => {
|
||||
if (response.data?.code === 401) {
|
||||
clearPersistedAuth();
|
||||
redirectToAdminLogin();
|
||||
return Promise.reject(new Error(response.data?.msg || "登录已过期"));
|
||||
const retryResponse = await retryRequestWithFreshToken(response.config as AuthRetryConfig);
|
||||
if (retryResponse) return retryResponse;
|
||||
|
||||
redirectAfterAuthExpired();
|
||||
return Promise.reject(new Error(getAuthErrorMessage(response.data)));
|
||||
}
|
||||
|
||||
return response.data;
|
||||
},
|
||||
(error) => {
|
||||
async (error) => {
|
||||
if (axios.isAxiosError(error) && error.response?.status === 401) {
|
||||
clearPersistedAuth();
|
||||
redirectToAdminLogin();
|
||||
const retryResponse = await retryRequestWithFreshToken(
|
||||
error.config as AuthRetryConfig | undefined,
|
||||
);
|
||||
if (retryResponse) return retryResponse;
|
||||
|
||||
redirectAfterAuthExpired();
|
||||
}
|
||||
|
||||
return Promise.reject(error);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user