|
@@ -26,6 +26,7 @@ export const constant = {
|
|
|
|
|
|
|
|
let currentData = {
|
|
let currentData = {
|
|
|
token: '',
|
|
token: '',
|
|
|
|
|
+ refreshToken: '',
|
|
|
identifier: '',
|
|
identifier: '',
|
|
|
};
|
|
};
|
|
|
|
|
|
|
@@ -38,6 +39,10 @@ function getErrorMessage(e) {
|
|
|
return e instanceof Error ? e.message : (typeof e === 'object' ? e : '' + e);
|
|
return e instanceof Error ? e.message : (typeof e === 'object' ? e : '' + e);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+async function saveCurrentData() {
|
|
|
|
|
+ await writeFile(constant.TokenSave, JSON.stringify(currentData));
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
// Axios 实例
|
|
// Axios 实例
|
|
|
// ========================================
|
|
// ========================================
|
|
|
|
|
|
|
@@ -64,16 +69,73 @@ axiosInstance.interceptors.request.use((value) => {
|
|
|
return value;
|
|
return value;
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
|
|
+let refreshPromise = null;
|
|
|
|
|
+
|
|
|
|
|
+async function tryRefreshToken() {
|
|
|
|
|
+ if (!currentData.refreshToken) return false;
|
|
|
|
|
+ if (refreshPromise) return refreshPromise;
|
|
|
|
|
+ refreshPromise = (async () => {
|
|
|
|
|
+ try {
|
|
|
|
|
+ const res = await axios.post(
|
|
|
|
|
+ `${constant.ServerUrl}/auth/refresh?identifier=${currentData.identifier}`,
|
|
|
|
|
+ { refreshToken: currentData.refreshToken },
|
|
|
|
|
+ { responseType: 'json', validateStatus: () => true }
|
|
|
|
|
+ );
|
|
|
|
|
+ if (res.data && res.data.success) {
|
|
|
|
|
+ currentData.token = {
|
|
|
|
|
+ authName: res.data.data.authName,
|
|
|
|
|
+ authKey: res.data.data.authKey,
|
|
|
|
|
+ };
|
|
|
|
|
+ if (res.data.data.refreshToken)
|
|
|
|
|
+ currentData.refreshToken = res.data.data.refreshToken;
|
|
|
|
|
+ await saveCurrentData();
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch {
|
|
|
|
|
+ // 刷新失败
|
|
|
|
|
+ }
|
|
|
|
|
+ return false;
|
|
|
|
|
+ })();
|
|
|
|
|
+ try {
|
|
|
|
|
+ return await refreshPromise;
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ refreshPromise = null;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
axiosInstance.interceptors.response.use((value) => {
|
|
axiosInstance.interceptors.response.use((value) => {
|
|
|
if (value.data.success) return value.data;
|
|
if (value.data.success) return value.data;
|
|
|
- else return Promise.reject(value.data);
|
|
|
|
|
|
|
+ const err = value.data;
|
|
|
|
|
+ err.__config = value.config;
|
|
|
|
|
+ return Promise.reject(err);
|
|
|
|
|
+}, (error) => {
|
|
|
|
|
+ return Promise.reject(error);
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+axiosInstance.interceptors.response.use(null, async (error) => {
|
|
|
|
|
+ const code = error?.code;
|
|
|
|
|
+ if (
|
|
|
|
|
+ (code === 40102 || code === 40103) &&
|
|
|
|
|
+ currentData.refreshToken &&
|
|
|
|
|
+ !error.__retried
|
|
|
|
|
+ ) {
|
|
|
|
|
+ const refreshed = await tryRefreshToken();
|
|
|
|
|
+ if (refreshed) {
|
|
|
|
|
+ const cfg = error.__config || error.config;
|
|
|
|
|
+ if (cfg) {
|
|
|
|
|
+ error.__retried = true;
|
|
|
|
|
+ return axiosInstance.request(cfg);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return Promise.reject(error);
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
// 认证初始化
|
|
// 认证初始化
|
|
|
// ========================================
|
|
// ========================================
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
- * 初始化认证模块,从本地加载 token
|
|
|
|
|
|
|
+ * 初始化认证模块,从本地加载 token,并检查登录状态
|
|
|
* @returns {Promise<void>}
|
|
* @returns {Promise<void>}
|
|
|
*/
|
|
*/
|
|
|
export async function initAuth() {
|
|
export async function initAuth() {
|
|
@@ -87,6 +149,19 @@ export async function initAuth() {
|
|
|
// 无 token 文件时使用默认值
|
|
// 无 token 文件时使用默认值
|
|
|
}
|
|
}
|
|
|
initIdentifier();
|
|
initIdentifier();
|
|
|
|
|
+
|
|
|
|
|
+ if (currentData.token) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ const res = await axiosInstance.get('/user/user-info');
|
|
|
|
|
+ if (res?.data) {
|
|
|
|
|
+ console.log(`当前登录用户: ${res.data.name || res.data.user} (ID: ${res.data.id})`);
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch {
|
|
|
|
|
+ console.log('未登录或登录已过期');
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ console.log('未登录');
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -126,7 +201,9 @@ export async function login(user) {
|
|
|
authName: res.data.authName,
|
|
authName: res.data.authName,
|
|
|
authKey: res.data.authKey,
|
|
authKey: res.data.authKey,
|
|
|
};
|
|
};
|
|
|
- await writeFile(constant.TokenSave, JSON.stringify(currentData));
|
|
|
|
|
|
|
+ if (res.data.refreshToken)
|
|
|
|
|
+ currentData.refreshToken = res.data.refreshToken;
|
|
|
|
|
+ await saveCurrentData();
|
|
|
console.log('登录成功');
|
|
console.log('登录成功');
|
|
|
} catch (e) {
|
|
} catch (e) {
|
|
|
console.error('登录失败', getErrorMessage(e));
|
|
console.error('登录失败', getErrorMessage(e));
|
|
@@ -138,7 +215,8 @@ export async function login(user) {
|
|
|
*/
|
|
*/
|
|
|
export async function logout() {
|
|
export async function logout() {
|
|
|
currentData.token = '';
|
|
currentData.token = '';
|
|
|
- await writeFile(constant.TokenSave, JSON.stringify(currentData));
|
|
|
|
|
|
|
+ currentData.refreshToken = '';
|
|
|
|
|
+ await saveCurrentData();
|
|
|
try {
|
|
try {
|
|
|
await axiosInstance.delete('/auth');
|
|
await axiosInstance.delete('/auth');
|
|
|
console.log('退出登录成功');
|
|
console.log('退出登录成功');
|