fix(router): validate server session before loading routes

This commit is contained in:
Kroytz committed 2026-07-19 00:32:14 +08:00
1 parent 17b2ba49a8
commit 6ffdbcb3d7
7 files changed
+40 -54

No files matched your search

+2 -3
View File
@@ -9,7 +9,7 @@ import axios, {
import { ElMessage, ElMessageBox, ElNotification } from 'element-plus'
import qs from 'qs'
import { config } from '@/config/axios/config'
import { getTenantId, removeAuthenticated } from '@/utils/auth'
import { getTenantId } from '@/utils/auth'
import errorCode from './errorCode'
import { resetRouter } from '@/router'
@@ -201,9 +201,8 @@ const handleAuthorized = () => {
type: 'warning'
}).then(() => {
resetRouter() // 重置静态路由表
removeAuthenticated()
isRelogin.show = false
// 干掉token后再走一次路由让它过router.beforeEach的校验
// 重新加载后由路由守卫向服务端确认会话
window.location.href = window.location.href
})
}
+37 -34
View File
@@ -1,7 +1,6 @@
import router from './router'
import router, { resetRouter } from './router'
import type { RouteRecordRaw } from 'vue-router'
import { isRelogin } from '@/config/axios/service'
import { isAuthenticated } from '@/utils/auth'
import { useTitle } from '@/hooks/web/useTitle'
import { useNProgress } from '@/hooks/web/useNProgress'
import { usePageLoading } from '@/hooks/web/usePageLoading'
@@ -60,42 +59,46 @@ const whiteList = [
router.beforeEach(async (to, from, next) => {
start()
loadStart()
if (isAuthenticated()) {
if (to.path === '/login') {
const userStore = useUserStoreWithOut()
if (whiteList.includes(to.path)) {
if (to.path === '/login' && userStore.getIsSetUser) {
next({ path: '/' })
} else {
// 获取所有字典
const dictStore = useDictStoreWithOut()
const userStore = useUserStoreWithOut()
const permissionStore = usePermissionStoreWithOut()
if (!dictStore.getIsSetDict) {
await dictStore.setDictMap()
}
if (!userStore.getIsSetUser) {
isRelogin.show = true
await userStore.setUserInfoAction()
isRelogin.show = false
// 后端过滤菜单
await permissionStore.generateRoutes(userStore.getMenus)
permissionStore.getAddRouters.forEach((route) => {
router.addRoute(route as unknown as RouteRecordRaw) // 动态添加可访问路由表
})
const redirectPath = from.query.redirect || to.path
// 修复跳转时不带参数的问题
const redirect = decodeURIComponent(redirectPath as string)
const { basePath, paramsObject: query } = parseURL(redirect)
const nextData = to.path === redirect ? { ...to, replace: true } : { path: redirect, query }
next(nextData)
} else {
next()
}
}
} else {
if (whiteList.indexOf(to.path) !== -1) {
next()
} else {
next(`/login?redirect=${to.fullPath}`) // 否则全部重定向到登录页
}
return
}
if (userStore.getIsSetUser) {
next()
return
}
isRelogin.show = true
try {
await userStore.setUserInfoAction()
const dictStore = useDictStoreWithOut()
if (!dictStore.getIsSetDict) {
await dictStore.setDictMap()
}
const permissionStore = usePermissionStoreWithOut()
await permissionStore.generateRoutes(userStore.getMenus)
permissionStore.getAddRouters.forEach((route) => {
router.addRoute(route as unknown as RouteRecordRaw)
})
const redirectPath = from.query.redirect || to.path
const redirect = decodeURIComponent(redirectPath as string)
const { paramsObject: query } = parseURL(redirect)
next(to.path === redirect ? { ...to, replace: true } : { path: redirect, query })
} catch {
userStore.resetState()
resetRouter()
next(`/login?redirect=${encodeURIComponent(to.fullPath)}`)
} finally {
isRelogin.show = false
}
})
@@ -1,6 +1,5 @@
import { store } from '@/store'
import { defineStore } from 'pinia'
import { isAuthenticated, removeAuthenticated } from '@/utils/auth'
import { getInfo, loginOut } from '@/api/login'
interface UserVO {
@@ -51,10 +50,6 @@ export const useUserStore = defineStore('admin-user', {
},
actions: {
async setUserInfoAction() {
if (!isAuthenticated()) {
this.resetState()
return null
}
const userInfo = await getInfo()
this.permissions = userInfo.permissions
this.roles = userInfo.roles
@@ -72,7 +67,6 @@ export const useUserStore = defineStore('admin-user', {
try {
await loginOut()
} finally {
removeAuthenticated()
this.resetState()
}
},
-6
View File
@@ -1,18 +1,12 @@
import { useCache, CACHE_KEY } from '@/hooks/web/useCache'
const { wsCache } = useCache()
const { wsCache: sessionCache } = useCache('sessionStorage')
wsCache.delete('ACCESS_TOKEN')
wsCache.delete('REFRESH_TOKEN')
wsCache.delete('user')
wsCache.delete('roleRouters')
const AuthenticatedKey = 'AUTHENTICATED'
export const isAuthenticated = () => sessionCache.get(AuthenticatedKey) === true
export const setAuthenticated = () => sessionCache.set(AuthenticatedKey, true)
export const removeAuthenticated = () => sessionCache.delete(AuthenticatedKey)
// ========== 账号相关 ==========
export type LoginFormType = {
@@ -252,7 +252,6 @@ const tryLogin = async () => {
const state = route?.query?.state as string
await LoginApi.socialLogin(type, code, state)
authUtil.setAuthenticated()
router.push({ path: redirect || '/' })
} catch (err) {}
@@ -297,7 +296,6 @@ const handleLogin = async (params) => {
} else {
authUtil.removeLoginForm()
}
authUtil.setAuthenticated()
if (!redirect) {
redirect = '/'
}
@@ -186,7 +186,6 @@ const handleLogin = async (params) => {
} else {
authUtil.removeLoginForm()
}
authUtil.setAuthenticated()
if (!redirect.value) {
redirect.value = '/'
}
@@ -97,7 +97,7 @@ import type { RouteLocationNormalizedLoaded } from 'vue-router'
import { useIcon } from '@/hooks/web/useIcon'
import { setTenantId, setAuthenticated } from '@/utils/auth'
import { setTenantId } from '@/utils/auth'
import { usePermissionStore } from '@/store/modules/permission'
import { getTenantIdByName, sendSmsCode, smsLogin } from '@/api/login'
import LoginFormTitle from './LoginFormTitle.vue'
@@ -196,7 +196,6 @@ const signIn = async () => {
smsVO.loginSms.code = loginData.loginForm.code
await smsLogin(smsVO.loginSms)
.then(async () => {
setAuthenticated()
if (!redirect.value) {
redirect.value = '/'
}