feat: 微服务版本 logout接口在配置错误的情况返回401的提示(解决死循环调用logout接口)

This commit is contained in:
dap 2025-07-18 18:23:55 +08:00
parent 6311f8edea
commit 296899fc33
4 changed files with 56 additions and 36 deletions

View File

@ -6,6 +6,7 @@
- websocket功能(默认关闭) - websocket功能(默认关闭)
- useVbenForm 增加 TimeRangePicker(时间区间选择) 组件 - useVbenForm 增加 TimeRangePicker(时间区间选择) 组件
- 字典(DictTag)支持fallback属性(未匹配到字典项时的回显) - 字典(DictTag)支持fallback属性(未匹配到字典项时的回显)
- 微服务版本 logout接口在配置错误的情况返回401的提示(解决死循环调用logout接口)
**REFACTOR** **REFACTOR**

View File

@ -1,12 +1,8 @@
import type { GrantType } from '@vben/common-ui'; import type { GrantType } from '@vben/common-ui';
import type { HttpResponse } from '@vben/request'; import type { HttpResponse } from '@vben/request';
import { h } from 'vue';
import { useAppConfig } from '@vben/hooks'; import { useAppConfig } from '@vben/hooks';
import { Modal } from 'ant-design-vue';
import { requestClient } from '#/api/request'; import { requestClient } from '#/api/request';
const { clientId, sseEnable } = useAppConfig( const { clientId, sseEnable } = useAppConfig(
@ -95,32 +91,8 @@ export async function loginApi(data: AuthApi.LoginParams) {
* *
* @returns void * @returns void
*/ */
export async function doLogout() { export function doLogout() {
const resp = await requestClient.post<HttpResponse<void>>( return requestClient.post<HttpResponse<void>>('/auth/logout');
'/auth/logout',
null,
{
isTransformResponse: false,
},
);
// 无奈之举 对错误用法的提示
if (resp.code === 401 && import.meta.env.DEV) {
Modal.destroyAll();
Modal.warn({
title: '后端配置出现错误',
centered: true,
content: h('div', { class: 'flex flex-col gap-2' }, [
`检测到你的logout接口返回了401, 导致前端一直进入循环逻辑???`,
...Array.from({ length: 3 }, () =>
h(
'span',
{ class: 'font-bold text-red-500 text-[18px]' },
'去检查你的后端配置!别盯着前端找问题了!这不是前端问题!',
),
),
]),
});
}
} }
/** /**

View File

@ -1,6 +1,6 @@
import { $t } from '@vben/locales'; import { $t } from '@vben/locales';
import { message } from 'ant-design-vue'; import { message, Modal } from 'ant-design-vue';
import { useAuthStore } from '#/store'; import { useAuthStore } from '#/store';
@ -38,11 +38,20 @@ export function commonExport(url: string, data: Record<string, any>) {
*/ */
export class UnauthorizedException extends Error {} export class UnauthorizedException extends Error {}
/**
* logout这种接口都返回401
*/
export class ImpossibleReturn401Exception extends Error {}
/** /**
* *
* api 401 * api 401
*/ */
let isLogoutProcessing = false; let isLogoutProcessing = false;
/**
* logout接口 logout又返回401 Logout逻辑死循环
*/
let lockLogoutRequest = false;
/** /**
* *
@ -50,17 +59,43 @@ let isLogoutProcessing = false;
*/ */
export function handleUnauthorizedLogout() { export function handleUnauthorizedLogout() {
const timeoutMsg = $t('http.loginTimeout'); const timeoutMsg = $t('http.loginTimeout');
/**
* lock logout接口
*
*/
if (lockLogoutRequest) {
throw new UnauthorizedException(timeoutMsg);
}
// 已经在登出过程中 不再执行 // 已经在登出过程中 不再执行
if (isLogoutProcessing) { if (isLogoutProcessing) {
throw new UnauthorizedException(timeoutMsg); throw new UnauthorizedException(timeoutMsg);
} }
isLogoutProcessing = true; isLogoutProcessing = true;
const userStore = useAuthStore(); const userStore = useAuthStore();
userStore.logout().finally(() => { userStore
message.error(timeoutMsg); .logout()
isLogoutProcessing = false; .catch((error) => {
}); /**
* logout接口返回了401
* Lock处理 ( )
*
*/
if (error instanceof ImpossibleReturn401Exception) {
lockLogoutRequest = true;
if (import.meta.env.DEV) {
Modal.error({
title: '提示',
centered: true,
content:
'检测到你的logout接口返回了401, 去检查你的后端配置 这已经不符合正常逻辑(该提示不会在非dev环境弹出)',
});
}
}
})
.finally(() => {
message.error(timeoutMsg);
isLogoutProcessing = false;
});
// 不再执行下面逻辑 // 不再执行下面逻辑
throw new UnauthorizedException(timeoutMsg); throw new UnauthorizedException(timeoutMsg);
} }

View File

@ -12,6 +12,10 @@ import { notification } from 'ant-design-vue';
import { defineStore } from 'pinia'; import { defineStore } from 'pinia';
import { doLogout, getUserInfoApi, loginApi, seeConnectionClose } from '#/api'; import { doLogout, getUserInfoApi, loginApi, seeConnectionClose } from '#/api';
import {
ImpossibleReturn401Exception,
UnauthorizedException,
} from '#/api/helper';
import { $t } from '#/locales'; import { $t } from '#/locales';
import { useDictStore } from './dict'; import { useDictStore } from './dict';
@ -83,6 +87,14 @@ export const useAuthStore = defineStore('auth', () => {
await Promise.all([seeConnectionClose(), doLogout()]); await Promise.all([seeConnectionClose(), doLogout()]);
} catch (error) { } catch (error) {
console.error(error); console.error(error);
/**
* 401
* 401
*
*/
if (error instanceof UnauthorizedException) {
throw new ImpossibleReturn401Exception(error.message);
}
} finally { } finally {
resetAllStores(); resetAllStores();
accessStore.setLoginExpired(false); accessStore.setLoginExpired(false);