+
{{ getFileName(file.name) }}
@@ -40,7 +40,7 @@
-
-
\ No newline at end of file
diff --git a/yudao-ui-admin/src/permission.js b/yudao-ui-admin/src/permission.js
index 57cad56f3..525b8b566 100644
--- a/yudao-ui-admin/src/permission.js
+++ b/yudao-ui-admin/src/permission.js
@@ -3,7 +3,7 @@ import store from './store'
import { Message } from 'element-ui'
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
-import { getToken } from '@/utils/auth'
+import { getAccessToken } from '@/utils/auth'
import { isRelogin } from '@/utils/request'
NProgress.configure({ showSpinner: false })
@@ -13,7 +13,7 @@ const whiteList = ['/login', '/social-login', '/auth-redirect', '/bind', '/regi
router.beforeEach((to, from, next) => {
NProgress.start()
- if (getToken()) {
+ if (getAccessToken()) {
to.meta.title && store.dispatch('settings/setTitle', to.meta.title)
/* has token*/
if (to.path === '/login') {
diff --git a/yudao-ui-admin/src/store/modules/user.js b/yudao-ui-admin/src/store/modules/user.js
index dac07d8f7..fbe209b75 100644
--- a/yudao-ui-admin/src/store/modules/user.js
+++ b/yudao-ui-admin/src/store/modules/user.js
@@ -1,9 +1,8 @@
import {login, logout, getInfo, socialQuickLogin, socialBindLogin, smsLogin} from '@/api/login'
-import { getToken, setToken, removeToken } from '@/utils/auth'
+import {getAccessToken, setToken, removeToken, getRefreshToken} from '@/utils/auth'
const user = {
state: {
- token: getToken(),
id: 0, // 用户编号
name: '',
avatar: '',
@@ -15,9 +14,6 @@ const user = {
SET_ID: (state, id) => {
state.id = id
},
- SET_TOKEN: (state, token) => {
- state.token = token
- },
SET_NAME: (state, name) => {
state.name = name
},
@@ -42,8 +38,8 @@ const user = {
return new Promise((resolve, reject) => {
login(username, password, code, uuid).then(res => {
res = res.data;
- setToken(res.token)
- commit('SET_TOKEN', res.token)
+ // 设置 token
+ setToken(res)
resolve()
}).catch(error => {
reject(error)
@@ -59,8 +55,8 @@ const user = {
return new Promise((resolve, reject) => {
socialQuickLogin(type, code, state).then(res => {
res = res.data;
- setToken(res.token)
- commit('SET_TOKEN', res.token)
+ // 设置 token
+ setToken(res)
resolve()
}).catch(error => {
reject(error)
@@ -78,8 +74,8 @@ const user = {
return new Promise((resolve, reject) => {
socialBindLogin(type, code, state, username, password).then(res => {
res = res.data;
- setToken(res.token)
- commit('SET_TOKEN', res.token)
+ // 设置 token
+ setToken(res)
resolve()
}).catch(error => {
reject(error)
@@ -93,8 +89,8 @@ const user = {
return new Promise((resolve, reject) => {
smsLogin(mobile,mobileCode).then(res => {
res = res.data;
- setToken(res.token)
- commit('SET_TOKEN', res.token)
+ // 设置 token
+ setToken(res)
resolve()
}).catch(error => {
reject(error)
@@ -142,7 +138,6 @@ const user = {
LogOut({ commit, state }) {
return new Promise((resolve, reject) => {
logout(state.token).then(() => {
- commit('SET_TOKEN', '')
commit('SET_ROLES', [])
commit('SET_PERMISSIONS', [])
removeToken()
@@ -151,15 +146,6 @@ const user = {
reject(error)
})
})
- },
-
- // 前端 登出
- FedLogOut({ commit }) {
- return new Promise(resolve => {
- commit('SET_TOKEN', '')
- removeToken()
- resolve()
- })
}
}
}
diff --git a/yudao-ui-admin/src/utils/auth.js b/yudao-ui-admin/src/utils/auth.js
index 08a43d6e2..0c00919ed 100644
--- a/yudao-ui-admin/src/utils/auth.js
+++ b/yudao-ui-admin/src/utils/auth.js
@@ -1,15 +1,22 @@
import Cookies from 'js-cookie'
-const TokenKey = 'Admin-Token'
+const AccessTokenKey = 'ACCESS_TOKEN'
+const RefreshTokenKey = 'REFRESH_TOKEN'
-export function getToken() {
- return Cookies.get(TokenKey)
+export function getAccessToken() {
+ return Cookies.get(AccessTokenKey)
+}
+
+export function getRefreshToken() {
+ return Cookies.get(RefreshTokenKey)
}
export function setToken(token) {
- return Cookies.set(TokenKey, token)
+ Cookies.set(AccessTokenKey, token.accessToken)
+ Cookies.set(RefreshTokenKey, token.refreshToken)
}
export function removeToken() {
- return Cookies.remove(TokenKey)
+ Cookies.remove(AccessTokenKey)
+ Cookies.remove(RefreshTokenKey)
}
diff --git a/yudao-ui-admin/src/utils/request.js b/yudao-ui-admin/src/utils/request.js
index ba675ec71..d15bf27ce 100644
--- a/yudao-ui-admin/src/utils/request.js
+++ b/yudao-ui-admin/src/utils/request.js
@@ -1,13 +1,19 @@
import axios from 'axios'
import { Notification, MessageBox, Message } from 'element-ui'
import store from '@/store'
-import { getToken } from '@/utils/auth'
+import {getAccessToken, getRefreshToken, setToken} from '@/utils/auth'
import errorCode from '@/utils/errorCode'
import Cookies from "js-cookie";
import {getPath, getTenantEnable} from "@/utils/ruoyi";
+import {refreshToken} from "@/api/login";
// 是否显示重新登录
export let isRelogin = { show: false };
+// Axios 无感知刷新令牌,参考 https://www.dashingdog.cn/article/11 与 https://segmentfault.com/a/1190000020210980 实现
+// 请求队列
+let requestList = []
+// 是否正在刷新中
+let isRefreshToken = false
axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'
// 创建axios实例
@@ -21,8 +27,8 @@ const service = axios.create({
service.interceptors.request.use(config => {
// 是否需要设置 token
const isToken = (config.headers || {}).isToken === false
- if (getToken() && !isToken) {
- config.headers['Authorization'] = 'Bearer ' + getToken() // 让每个请求携带自定义token 请根据实际情况自行修改
+ if (getAccessToken() && !isToken) {
+ config.headers['Authorization'] = 'Bearer ' + getAccessToken() // 让每个请求携带自定义token 请根据实际情况自行修改
}
// 设置租户
if (getTenantEnable()) {
@@ -60,29 +66,44 @@ service.interceptors.request.use(config => {
})
// 响应拦截器
-service.interceptors.response.use(res => {
+service.interceptors.response.use( async res => {
// 未设置状态码则默认成功状态
const code = res.data.code || 200;
// 获取错误信息
const msg = errorCode[code] || res.data.msg || errorCode['default']
if (code === 401) {
- if (!isRelogin.show) {
- isRelogin.show = true;
- MessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', {
- confirmButtonText: '重新登录',
- cancelButtonText: '取消',
- type: 'warning'
- }
- ).then(() => {
- isRelogin.show = false;
- store.dispatch('LogOut').then(() => {
- location.href = getPath('/index');
+ // 如果未认证,并且未进行刷新令牌,说明可能是访问令牌过期了
+ if (!isRefreshToken) {
+ isRefreshToken = true;
+ // 1. 如果获取不到刷新令牌,则只能执行登出操作
+ if (!getRefreshToken()) {
+ return handleAuthorized();
+ }
+ // 2. 进行刷新访问令牌
+ try {
+ const refreshTokenRes = await refreshToken()
+ // 2.1 刷新成功,则回放队列的请求 + 当前请求
+ setToken(refreshTokenRes.data)
+ requestList.forEach(cb => cb())
+ return service(res.config)
+ } catch (e) {
+ // 2.2 刷新失败,则只能执行登出操作
+ // 为什么需要 catch 异常呢?刷新失败时,请求因为 Promise.reject 触发异常。
+ return handleAuthorized();
+ } finally {
+ requestList = []
+ isRefreshToken = false
+ }
+ } else {
+ // 添加到队列,等待刷新获取到新的令牌
+ return new Promise(resolve => {
+ requestList.push(() => {
+ config.headers['Authorization'] = 'Bearer ' + getAccessToken() // 让每个请求携带自定义token 请根据实际情况自行修改
+ resolve(service(config))
})
- }).catch(() => {
- isRelogin.show = false;
- });
+ })
}
- return Promise.reject('无效的会话,或者会话已过期,请重新登录。')
+ return handleAuthorized();
} else if (code === 500) {
Message({
message: msg,
@@ -133,9 +154,29 @@ service.interceptors.response.use(res => {
export function getBaseHeader() {
return {
- 'Authorization': "Bearer " + getToken(),
+ 'Authorization': "Bearer " + getAccessToken(),
'tenant-id': Cookies.get('tenantId'),
}
}
+function handleAuthorized() {
+ if (!isRelogin.show) {
+ isRelogin.show = true;
+ MessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', {
+ confirmButtonText: '重新登录',
+ cancelButtonText: '取消',
+ type: 'warning'
+ }
+ ).then(() => {
+ isRelogin.show = false;
+ store.dispatch('LogOut').then(() => {
+ location.href = getPath('/index');
+ })
+ }).catch(() => {
+ isRelogin.show = false;
+ });
+ }
+ return Promise.reject('无效的会话,或者会话已过期,请重新登录。')
+}
+
export default service
diff --git a/yudao-ui-admin/src/views/infra/file/index.vue b/yudao-ui-admin/src/views/infra/file/index.vue
index 20f5b738b..0b02a3dae 100644
--- a/yudao-ui-admin/src/views/infra/file/index.vue
+++ b/yudao-ui-admin/src/views/infra/file/index.vue
@@ -77,7 +77,7 @@
diff --git a/yudao-ui-admin/src/views/system/session/index.vue b/yudao-ui-admin/src/views/system/oauth2/token/index.vue
similarity index 55%
rename from yudao-ui-admin/src/views/system/session/index.vue
rename to yudao-ui-admin/src/views/system/oauth2/token/index.vue
index 10135403c..a6cb9131c 100644
--- a/yudao-ui-admin/src/views/system/session/index.vue
+++ b/yudao-ui-admin/src/views/system/oauth2/token/index.vue
@@ -3,11 +3,14 @@
-
-
+
+
-
-
+
+
+
+
搜索
@@ -16,20 +19,28 @@
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
{{ parseTime(scope.row.createTime) }}
+
+
+ {{ parseTime(scope.row.expiresTime) }}
+
+
强退
+ v-hasPermi="['system:oauth2-token:delete']">强退
@@ -40,10 +51,10 @@