Files
lc_frontend/src/permission.ts
yang chen 82930a7f2e fix(permission): 修复SSO重定向URL构造问题
- 正确处理路由中的查询参数
- 使用URLSearchParams构造查询字符串
- 对重定向URL进行编码以确保安全性
- 保持原有路径参数不变
- 提高SSO登录流程的稳定性
2025-12-12 14:56:27 +08:00

133 lines
4.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import router from './router'
import type { RouteRecordRaw } from 'vue-router'
import { isRelogin } from '@/config/axios/service'
import { getAccessToken } from '@/utils/auth'
import { useTitle } from '@/hooks/web/useTitle'
import { useNProgress } from '@/hooks/web/useNProgress'
import { usePageLoading } from '@/hooks/web/usePageLoading'
import { useDictStoreWithOut } from '@/store/modules/dict'
import { useUserStoreWithOut } from '@/store/modules/user'
import { useLowStoreWithOut } from '@/store/modules/low'
import { usePermissionStoreWithOut } from '@/store/modules/permission'
import * as LoginApi from '@/api/login'
import * as authUtil from '@/utils/auth'
const { start, done } = useNProgress()
const { loadStart, loadDone } = usePageLoading()
const parseURL = (
url: string | null | undefined
): { basePath: string; paramsObject: { [key: string]: string } } => {
// 如果输入为 null 或 undefined返回空字符串和空对象
if (url == null) {
return { basePath: '', paramsObject: {} }
}
// 找到问号 (?) 的位置,它之前是基础路径,之后是查询参数
const questionMarkIndex = url.indexOf('?')
let basePath = url
const paramsObject: { [key: string]: string } = {}
// 如果找到了问号,说明有查询参数
if (questionMarkIndex !== -1) {
// 获取 basePath
basePath = url.substring(0, questionMarkIndex)
// 从 URL 中获取查询字符串部分
const queryString = url.substring(questionMarkIndex + 1)
// 使用 URLSearchParams 遍历参数
const searchParams = new URLSearchParams(queryString)
searchParams.forEach((value, key) => {
// 封装进 paramsObject 对象
paramsObject[key] = value
})
}
// 返回 basePath 和 paramsObject
return { basePath, paramsObject }
}
// 路由不重定向白名单
const whiteList = [
'/login',
'/social-login',
'/auth-redirect',
'/bind',
'/register',
'/oauthLogin/gitee'
]
// 路由加载前
router.beforeEach(async (to, from, next) => {
start()
loadStart()
if (getAccessToken()) {
if (to.path === '/login') {
next({ path: '/' })
} else {
// 获取所有字典
const dictStore = useDictStoreWithOut()
const userStore = useUserStoreWithOut()
const lowStore = useLowStoreWithOut()
const permissionStore = usePermissionStoreWithOut()
if (!dictStore.getIsSetDict) await dictStore.setDictMap()
if (!lowStore.getIsSetRegion) await lowStore.setRegion()
if (!userStore.getIsSetUser) {
isRelogin.show = true
await userStore.setUserInfoAction()
isRelogin.show = false
// 后端过滤菜单
await permissionStore.generateRoutes()
permissionStore.getAddRouters.forEach((route) => {
try {
router.addRoute(route as unknown as RouteRecordRaw) // 动态添加可访问路由表
} catch (error) {
console.warn(`路由注册异常请检查菜单配置是否正确\n 菜单名称:${route.meta.title}\n 路由地址:${route.path}`)
}
})
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 || to.path.indexOf('/form/external/') === 0) {
next()
} else {
if(import.meta.env.VITE_DEFAULT_SSO =='true'){
authUtil.setTenantId("1")
// 正确构造包含查询参数的重定向URL
let redirectUrl = to.fullPath;
if (Object.keys(to.query).length > 0) {
const queryParams = new URLSearchParams(to.query as Record<string, string>).toString();
redirectUrl = `${to.path}?${queryParams}`;
}
const redirectUri =
location.origin +
'/social-login?' +
`type=100&redirect=${encodeURIComponent(redirectUrl)}`
// 进行跳转
const res = await LoginApi.socialAuthRedirect(100, encodeURIComponent(redirectUri))
window.location.href = res
}else{
next(`/login?redirect=${to.fullPath}`) // 否则全部重定向到登录页
}
}
}
})
router.afterEach((to) => {
useTitle(to?.meta?.title as string)
done() // 结束Progress
loadDone()
})