feat: 微服务版本 logout接口在配置错误的情况返回401的提示(解决死循环调用logout接口)
This commit is contained in:
parent
6311f8edea
commit
296899fc33
@ -6,6 +6,7 @@
|
|||||||
- websocket功能(默认关闭)
|
- websocket功能(默认关闭)
|
||||||
- useVbenForm 增加 TimeRangePicker(时间区间选择) 组件
|
- useVbenForm 增加 TimeRangePicker(时间区间选择) 组件
|
||||||
- 字典(DictTag)支持fallback属性(未匹配到字典项时的回显)
|
- 字典(DictTag)支持fallback属性(未匹配到字典项时的回显)
|
||||||
|
- 微服务版本 logout接口在配置错误的情况返回401的提示(解决死循环调用logout接口)
|
||||||
|
|
||||||
**REFACTOR**
|
**REFACTOR**
|
||||||
|
|
||||||
|
|||||||
@ -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]' },
|
|
||||||
'去检查你的后端配置!别盯着前端找问题了!这不是前端问题!',
|
|
||||||
),
|
|
||||||
),
|
|
||||||
]),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user