From 8f9d48be28aae04422edb407b18107e379cbda23 Mon Sep 17 00:00:00 2001
From: linwe <872216996@qq.com>
Date: Thu, 21 Nov 2024 13:48:24 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/main'
---
src/store/login.js | 33 ++++++++++
src/pages/layout/index.vue | 4
src/utils/http.js | 94 +++++++++++++++++++++++++++++++
src/api/user.js | 27 +++++++++
4 files changed, 154 insertions(+), 4 deletions(-)
diff --git a/src/api/user.js b/src/api/user.js
index c96cec6..dcad943 100644
--- a/src/api/user.js
+++ b/src/api/user.js
@@ -1,3 +1,13 @@
+/*
+ * @Author: shuishen 1109946754@qq.com
+ * @Date: 2024-10-30 15:34:08
+ * @LastEditors: shuishen 1109946754@qq.com
+ * @LastEditTime: 2024-11-21 12:18:06
+ * @FilePath: \bigScreen\src\api\user.js
+ * @Description:
+ *
+ * Copyright (c) 2024 by shuishen, All Rights Reserved.
+ */
import request from 'utils/http'
export const loginByUsername = (tenantId, deptId, roleId, username, password, type, key, code) =>
@@ -26,4 +36,21 @@
url: '/blade-auth/oauth/logout',
method: 'get',
authorization: false,
+ })
+
+export const refreshToken = (refresh_token, tenantId, deptId, roleId) =>
+ request({
+ url: '/blade-auth/oauth/token',
+ method: 'post',
+ headers: {
+ 'Tenant-Id': tenantId,
+ 'Dept-Id': deptId || '',
+ 'Role-Id': roleId || '',
+ },
+ params: {
+ tenantId,
+ refresh_token,
+ grant_type: 'refresh_token',
+ scope: 'all',
+ },
})
\ No newline at end of file
diff --git a/src/pages/layout/index.vue b/src/pages/layout/index.vue
index 84ec6ce..e95d8fc 100644
--- a/src/pages/layout/index.vue
+++ b/src/pages/layout/index.vue
@@ -2,8 +2,8 @@
* @Author: shuishen 1109946754@qq.com
* @Date: 2022-08-18 16:18:24
* @LastEditors: shuishen 1109946754@qq.com
- * @LastEditTime: 2024-11-11 18:36:37
- * @FilePath: \bigScreen\src\views\layout\index.vue
+ * @LastEditTime: 2024-11-21 12:29:12
+ * @FilePath: \bigScreen\src\pages\layout\index.vue
* @Description:
*
* Copyright (c) 2022 by shuishen 1109946754@qq.com, All Rights Reserved.
diff --git a/src/store/login.js b/src/store/login.js
index 70269d8..59d939d 100644
--- a/src/store/login.js
+++ b/src/store/login.js
@@ -1,13 +1,15 @@
// src/stores/useUserStore.js
import {
loginByUsername,
- logout
+ logout,
+ refreshToken,
} from '@/api/user'
import { defineStore } from 'pinia'
import md5 from 'js-md5'
import {
ElMessage
} from 'element-plus'
+import { validatenull } from '@/utils/validate'
export const useLogin = defineStore('login', {
// 存储状态的地方,相当于 Vuex 的 state
@@ -91,6 +93,35 @@
})
})
},
+
+ RefreshToken (userInfo = {}) {
+ return new Promise((resolve, reject) => {
+ refreshToken(
+ this.refreshToken,
+ this.tenantId,
+ !validatenull(userInfo) ? userInfo.deptId : this.userInfo.dept_id,
+ !validatenull(userInfo) ? userInfo.roleId : this.userInfo.role_id
+ )
+ .then(res => {
+ const data = res.data
+ this.SET_TOKEN(data.access_token)
+ this.SET_REFRESH_TOKEN(data.refresh_token)
+ this.SET_USER_INFO(data)
+ resolve()
+ })
+ .catch(error => {
+ reject(error)
+ })
+ })
+ },
+
+ removeToken () {
+ this.SET_TOKEN('')
+ },
+
+ removeRefreshToken () {
+ this.SET_REFRESH_TOKEN('')
+ }
},
persist: {
diff --git a/src/utils/http.js b/src/utils/http.js
index 3fd00b4..2cf82e0 100644
--- a/src/utils/http.js
+++ b/src/utils/http.js
@@ -6,7 +6,7 @@
* isToken是否需要token
*/
import axios from 'axios'
-// import router from '@/router/'
+import router from '@/router/index'
import {
isURL,
@@ -27,6 +27,10 @@
// 全局未授权错误提示状态,只提示一次
let isErrorShown = false
+
+// 全局锁机制相关变量
+let isRefreshing = false // 标记当前是否正在刷新token
+let refreshTokenPromise = null // 刷新token的Promise,避免重复请求
// 超时时间设置为10分钟,部分接口上传比较慢,如固件上传
axios.defaults.timeout = 600000
@@ -103,6 +107,8 @@
//http response拦截
axios.interceptors.response.use(
res => {
+ const store = useLogin()
+
NProgress.done()
const status = res.data.error_code || res.data.code || res.status
const statusWhiteList = []
@@ -112,6 +118,92 @@
//如果在白名单里则自行catch逻辑处理
if (statusWhiteList.includes(status)) return Promise.reject(res)
+ // 如果是401并且没有重试过,尝试刷新token
+ if (status === 401 && !config._retry) {
+ config._retry = true
+
+ // 如果当前已经在刷新token,等待刷新完成
+ if (isRefreshing) {
+ return refreshTokenPromise.then(() => {
+ const meta = config.meta || {}
+ const isToken = meta.isToken === false
+ const cryptoToken = config.cryptoToken === true
+
+ const token = store.token
+
+ if (token && !isToken) {
+ config.headers['Blade-Auth'] = cryptoToken
+ ? 'crypto ' + crypto.encryptAES(token, crypto.cryptoKey)
+ : 'bearer ' + token
+ }
+ return axios(config)
+ })
+ }
+
+ // 开始刷新token
+ isRefreshing = true
+
+ // 调用RefreshToken action来刷新token
+ refreshTokenPromise = store.RefreshToken().then(() => {
+ const meta = config.meta || {}
+ const isToken = meta.isToken === false
+ const cryptoToken = config.cryptoToken === true
+ // 获取刷新后的token
+ const token = store.token
+
+ if (token && !isToken) {
+ config.headers['Blade-Auth'] = cryptoToken
+ ? 'crypto ' + crypto.encryptAES(token, crypto.cryptoKey)
+ : 'bearer ' + token
+ }
+ return axios(config)
+ }).catch(() => {
+ isRefreshing = false // 重置刷新标志
+ // 首次报错时提示
+ if (!isErrorShown) {
+ isErrorShown = true
+ ElMessage({
+ message: '用户令牌过期,请重新登录',
+ type: 'error',
+ })
+ }
+ // 清除token信息
+ store.removeToken()
+ store.removeRefreshToken()
+ // 重定向到登录页
+ store.LogOut().then(res => {
+ router.push({
+ path: '/login'
+ })
+ })
+ return Promise.reject(new Error(message))
+ })
+
+ return refreshTokenPromise
+ }
+
+ // 如果是401并且已经重试过,直接跳转到登录页面
+ if (status === 401 && config._retry) {
+ if (!isErrorShown) {
+ isErrorShown = true
+ ElMessage({
+ message: '用户令牌过期,请重新登录',
+ type: 'error',
+ })
+ }
+ // 清除token信息
+ store.removeToken()
+ store.removeRefreshToken()
+
+ // 重定向到登录页
+ store.LogOut().then(res => {
+ router.push({
+ path: '/login'
+ })
+ })
+ return Promise.reject(new Error(message))
+ }
+
// 如果请求为oauth2错误码则首次报错时提示
if (status > 2000 && !validatenull(res.data.error_description)) {
// 首次报错时提示
--
Gitblit v1.9.3