【修改】 1、强制登出页面优化;2、系统token管理优化

This commit is contained in:
dlaren
2025-08-30 20:28:33 +08:00
parent 1e14e1df2c
commit 1f798663ba
2 changed files with 68 additions and 78 deletions

View File

@@ -21,9 +21,9 @@ const ignoreMsgs = [
export const isRelogin = { show: false } export const isRelogin = { show: false }
// Axios 无感知刷新令牌,参考 https://www.dashingdog.cn/article/11 与 https://segmentfault.com/a/1190000020210980 实现 // Axios 无感知刷新令牌,参考 https://www.dashingdog.cn/article/11 与 https://segmentfault.com/a/1190000020210980 实现
// 请求队列 // 请求队列
let requestList: any[] = [] const requestList: any[] = []
// 是否正在刷新中 // 是否正在刷新中
let isRefreshToken = false const isRefreshToken = false
// 请求白名单无须token的接口 // 请求白名单无须token的接口
const whiteList: string[] = ['/login', '/refresh-token'] const whiteList: string[] = ['/login', '/refresh-token']
@@ -109,45 +109,48 @@ service.interceptors.response.use(
// 如果是忽略的错误码,直接返回 msg 异常 // 如果是忽略的错误码,直接返回 msg 异常
return Promise.reject(msg) return Promise.reject(msg)
} else if (code === 401) { } else if (code === 401) {
// 如果未认证,并且未进行刷新令牌,说明可能是访问令牌过期了 // 如果未进行认证,返回登录页面(切换浏览器等均会触发)
if (!isRefreshToken) { console.log(msg)
isRefreshToken = true return handleAuthorized()
// 1. 如果获取不到刷新令牌,则只能执行登出操作 // // 如果未认证,并且未进行刷新令牌,说明可能是访问令牌过期了
if (!getRefreshToken()) { // if (!isRefreshToken) {
return handleAuthorized() // isRefreshToken = true
} // // 1. 如果获取不到刷新令牌,则只能执行登出操作
// 2. 进行刷新访问令牌 // if (!getRefreshToken()) {
try { // return handleAuthorized()
const refreshTokenRes = await refreshToken() // }
// 2.1 刷新成功,则回放队列的请求 + 当前请求 // // 2. 进行刷新访问令牌
setToken((await refreshTokenRes).data.data) // try {
config.headers!.Authorization = 'Bearer ' + getAccessToken() // const refreshTokenRes = await refreshToken()
requestList.forEach((cb: any) => { // // 2.1 刷新成功,则回放队列的请求 + 当前请求
cb() // setToken((await refreshTokenRes).data.data)
}) // config.headers!.Authorization = 'Bearer ' + getAccessToken()
requestList = [] // requestList.forEach((cb: any) => {
return service(config) // cb()
} catch (e) { // })
// 为什么需要 catch 异常呢?刷新失败时,请求因为 Promise.reject 触发异常。 // requestList = []
// 2.2 刷新失败,只回放队列的请求 // return service(config)
requestList.forEach((cb: any) => { // } catch (e) {
cb() // // 为什么需要 catch 异常呢?刷新失败时,请求因为 Promise.reject 触发异常。
}) // // 2.2 刷新失败,只回放队列的请求
// 提示是否要登出。即不回放当前请求!不然会形成递归 // requestList.forEach((cb: any) => {
return handleAuthorized() // cb()
} finally { // })
requestList = [] // // 提示是否要登出。即不回放当前请求!不然会形成递归
isRefreshToken = false // return handleAuthorized()
} // } finally {
} else { // requestList = []
// 添加到队列,等待刷新获取到新的令牌 // isRefreshToken = false
return new Promise((resolve) => { // }
requestList.push(() => { // } else {
config.headers!.Authorization = 'Bearer ' + getAccessToken() // 让每个请求携带自定义token 请根据实际情况自行修改 // // 添加到队列,等待刷新获取到新的令牌
resolve(service(config)) // return new Promise((resolve) => {
}) // requestList.push(() => {
}) // config.headers!.Authorization = 'Bearer ' + getAccessToken() // 让每个请求携带自定义token 请根据实际情况自行修改
} // resolve(service(config))
// })
// })
// }
} else if (code === 500) { } else if (code === 500) {
ElMessage.error(t('sys.api.errMsg500')) ElMessage.error(t('sys.api.errMsg500'))
return Promise.reject(new Error(msg)) return Promise.reject(new Error(msg))

View File

@@ -81,6 +81,29 @@
/> />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col v-if="isTrueLoginForAdminPassWord" :span="24" style="padding-right: 10px; padding-left: 10px">
<el-form-item prop="password">
<el-input
v-model="adminPassword"
:placeholder="t('请输入管理员密码')"
:prefix-icon="iconLock"
show-password
type="password"
@keyup.enter="getCode()"
/>
</el-form-item>
</el-col>
<el-col v-if="isTrueLoginForAdminPassWord" :span="24" style="padding-right: 10px; padding-left: 10px">
<el-form-item>
<XButton
:loading="loginLoading"
:title="t('使用管理员密码进行强制退出后,再点击登录按钮')"
class="w-[100%]"
type="primary"
@click="loginOutAdminPassword()"
/>
</el-form-item>
</el-col>
<Verify <Verify
v-if="loginData.captchaEnable === 'true'" v-if="loginData.captchaEnable === 'true'"
ref="verify" ref="verify"
@@ -149,39 +172,6 @@
<!-- </el-col>--> <!-- </el-col>-->
</el-row> </el-row>
</el-form> </el-form>
<el-dialog
v-model="isTrueLoginForAdmin"
title="提示"
width="500"
:before-close="handleClose"
>
<span>是否使用管理员密码强制退出该用户</span>
<template #footer>
<div class="dialog-footer">
<el-button @click="isTrueLoginForAdmin = false">取消</el-button>
<el-button type="primary" @click="openLoginForAdminPassWord()">
确定
</el-button>
</div>
</template>
</el-dialog>
<el-dialog
v-model="isTrueLoginForAdminPassWord"
title="提示"
width="500"
:before-close="handleClose"
>
<span>管理员密码</span>
<el-input v-model="adminPassword" style="width: 240px" placeholder="请输入管理员密码" />
<template #footer>
<div class="dialog-footer">
<el-button @click="isTrueLoginForAdminPassWord = false">取消</el-button>
<el-button type="primary" @click="loginOutAdminPassword()">
确定
</el-button>
</div>
</template>
</el-dialog>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { ElLoading } from 'element-plus' import { ElLoading } from 'element-plus'
@@ -197,7 +187,6 @@ import { LoginStateEnum, useFormValid, useLoginState } from './useLogin'
defineOptions({ name: 'LoginForm' }) defineOptions({ name: 'LoginForm' })
const isTrueLoginForAdmin = ref(false)
const isTrueLoginForAdminPassWord = ref(false) const isTrueLoginForAdminPassWord = ref(false)
const adminPassword = ref('') const adminPassword = ref('')
@@ -273,7 +262,6 @@ const getTenantId = async () => {
} }
// 使用管理员密码登出登录的账号 // 使用管理员密码登出登录的账号
const openLoginForAdminPassWord = () => { const openLoginForAdminPassWord = () => {
isTrueLoginForAdmin.value = false
isTrueLoginForAdminPassWord.value = true isTrueLoginForAdminPassWord.value = true
} }
const loginOutAdminPassword = async () => { const loginOutAdminPassword = async () => {
@@ -284,7 +272,6 @@ const loginOutAdminPassword = async () => {
LoginApi.refreshLogout(data).then((res) => { LoginApi.refreshLogout(data).then((res) => {
if (res) { if (res) {
message.success(res) message.success(res)
isTrueLoginForAdmin.value = false
isTrueLoginForAdminPassWord.value = false isTrueLoginForAdminPassWord.value = false
} }
}).catch((err) => { }).catch((err) => {
@@ -353,7 +340,7 @@ const handleLogin = async (params: any) => {
} }
} finally { } finally {
// 弹出输入管理员密码并重新进行登录 // 弹出输入管理员密码并重新进行登录
isTrueLoginForAdmin.value = true isTrueLoginForAdminPassWord.value = true
loginLoading.value = false loginLoading.value = false
loading.value.close() loading.value.close()
} }