feat(router): 增加强制登录配置选项
添加 VITE_AUTH_ROUTE_FORCE_LOGIN 环境变量以控制是否强制用户登录 当设置为 Y 时,未登录用户访问非白名单路由将被重定向到登录页 同时更新开发环境配置并添加相应的 TypeScript 类型定义
This commit is contained in:
@ -24,6 +24,9 @@ VITE_ICON_LOCAL_PREFIX=icon-local
|
|||||||
# 认证路由模式: static (静态) | dynamic (动态)
|
# 认证路由模式: static (静态) | dynamic (动态)
|
||||||
VITE_AUTH_ROUTE_MODE=static
|
VITE_AUTH_ROUTE_MODE=static
|
||||||
|
|
||||||
|
# 是否强制登录: Y (开启) | N (关闭)
|
||||||
|
VITE_AUTH_ROUTE_FORCE_LOGIN=N
|
||||||
|
|
||||||
# 静态认证路由的主页
|
# 静态认证路由的主页
|
||||||
VITE_ROUTE_HOME=home
|
VITE_ROUTE_HOME=home
|
||||||
|
|
||||||
|
|||||||
@ -3,10 +3,10 @@
|
|||||||
|
|
||||||
# VITE_SERVICE_BASE_URL=http://192.168.5.140:9999
|
# VITE_SERVICE_BASE_URL=http://192.168.5.140:9999
|
||||||
|
|
||||||
VITE_SERVICE_BASE_URL=https://api.qyzhjy.com
|
# VITE_SERVICE_BASE_URL=https://api.qyzhjy.com
|
||||||
|
|
||||||
|
VITE_SERVICE_BASE_URL=http://172.16.10.130:5000
|
||||||
|
|
||||||
# other backend service base url, test environment
|
|
||||||
VITE_OTHER_SERVICE_BASE_URL= `{
|
VITE_OTHER_SERVICE_BASE_URL= `{
|
||||||
"demo": "http://localhost:9528"
|
"demo": "http://localhost:9528"
|
||||||
}`
|
}`
|
||||||
|
|||||||
@ -12,9 +12,9 @@ import { useRouteStore } from '@/store/modules/route'
|
|||||||
import { localStg } from '@/utils/storage'
|
import { localStg } from '@/utils/storage'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* create route guard
|
* 创建路由守卫
|
||||||
*
|
*
|
||||||
* @param router router instance
|
* @param router 路由实例
|
||||||
*/
|
*/
|
||||||
export function createRouteGuard(router: Router) {
|
export function createRouteGuard(router: Router) {
|
||||||
router.beforeEach(async (to, from, next) => {
|
router.beforeEach(async (to, from, next) => {
|
||||||
@ -38,39 +38,43 @@ export function createRouteGuard(router: Router) {
|
|||||||
const hasRole = authStore.userInfo.roles.some(role => routeRoles.includes(role))
|
const hasRole = authStore.userInfo.roles.some(role => routeRoles.includes(role))
|
||||||
const hasAuth = authStore.isStaticSuper || !routeRoles.length || hasRole
|
const hasAuth = authStore.isStaticSuper || !routeRoles.length || hasRole
|
||||||
|
|
||||||
// if it is login route when logged in, then switch to the root page
|
// 如果已登录且访问的是登录页,则跳转到根页面
|
||||||
if (to.name === loginRoute && isLogin) {
|
if (to.name === loginRoute && isLogin) {
|
||||||
next({ name: rootRoute })
|
next({ name: rootRoute })
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the route does not need login, then it is allowed to access directly
|
// 如果路由不需要登录,则直接允许访问
|
||||||
if (!needLogin) {
|
if (!needLogin) {
|
||||||
handleRouteSwitch(to, from, next)
|
handleRouteSwitch(to, from, next)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// the route need login but the user is not logged in, then switch to the login page
|
// 如果路由需要登录但用户未登录,则跳转到登录页
|
||||||
if (!isLogin) {
|
const isAuthRouteForceLogin = import.meta.env.VITE_AUTH_ROUTE_FORCE_LOGIN === 'Y'
|
||||||
|
const whiteList: string[] = ['user']
|
||||||
|
const isInWhiteList = whiteList.includes(to.name as string)
|
||||||
|
|
||||||
|
if (isAuthRouteForceLogin && !isLogin && !isInWhiteList) {
|
||||||
next({ name: loginRoute, query: { redirect: to.fullPath } })
|
next({ name: loginRoute, query: { redirect: to.fullPath } })
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the user is logged in but does not have authorization, then switch to the 403 page
|
// 如果用户已登录但没有权限,则跳转到 403 页面
|
||||||
if (!hasAuth) {
|
if (!hasAuth) {
|
||||||
next({ name: noAuthorizationRoute })
|
next({ name: noAuthorizationRoute })
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// switch route normally
|
// 正常跳转路由
|
||||||
handleRouteSwitch(to, from, next)
|
handleRouteSwitch(to, from, next)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* initialize route
|
* 初始化路由
|
||||||
*
|
*
|
||||||
* @param to to route
|
* @param to 目标路由
|
||||||
*/
|
*/
|
||||||
async function initRoute(to: RouteLocationNormalized): Promise<RouteLocationRaw | null> {
|
async function initRoute(to: RouteLocationNormalized): Promise<RouteLocationRaw | null> {
|
||||||
const routeStore = useRouteStore()
|
const routeStore = useRouteStore()
|
||||||
@ -78,12 +82,12 @@ async function initRoute(to: RouteLocationNormalized): Promise<RouteLocationRaw
|
|||||||
const notFoundRoute: RouteKey = 'not-found'
|
const notFoundRoute: RouteKey = 'not-found'
|
||||||
const isNotFoundRoute = to.name === notFoundRoute
|
const isNotFoundRoute = to.name === notFoundRoute
|
||||||
|
|
||||||
// if the constant route is not initialized, then initialize the constant route
|
// 如果常量路由未初始化,则初始化常量路由
|
||||||
if (!routeStore.isInitConstantRoute) {
|
if (!routeStore.isInitConstantRoute) {
|
||||||
await routeStore.initConstantRoute()
|
await routeStore.initConstantRoute()
|
||||||
|
|
||||||
// the route is captured by the "not-found" route because the constant route is not initialized
|
// 由于常量路由未初始化,路由被“未找到”路由捕获
|
||||||
// after the constant route is initialized, redirect to the original route
|
// 常量路由初始化后,重定向到原始路由
|
||||||
const path = to.fullPath
|
const path = to.fullPath
|
||||||
const location: RouteLocationRaw = {
|
const location: RouteLocationRaw = {
|
||||||
path,
|
path,
|
||||||
@ -97,15 +101,19 @@ async function initRoute(to: RouteLocationNormalized): Promise<RouteLocationRaw
|
|||||||
|
|
||||||
const isLogin = Boolean(localStg.get('token'))
|
const isLogin = Boolean(localStg.get('token'))
|
||||||
|
|
||||||
if (!isLogin) {
|
const isAuthRouteForceLogin = import.meta.env.VITE_AUTH_ROUTE_FORCE_LOGIN === 'Y'
|
||||||
// if the user is not logged in and the route is a constant route but not the "not-found" route, then it is allowed to access.
|
const whiteList: string[] = ['user']
|
||||||
|
const isInWhiteList = whiteList.includes(to.name as string)
|
||||||
|
|
||||||
|
if (isAuthRouteForceLogin && !isLogin && !isInWhiteList) {
|
||||||
|
// 如果用户未登录且路由是常量路由但不是“未找到”路由,则允许访问。
|
||||||
if (to.meta.constant && !isNotFoundRoute) {
|
if (to.meta.constant && !isNotFoundRoute) {
|
||||||
routeStore.onRouteSwitchWhenNotLoggedIn()
|
routeStore.onRouteSwitchWhenNotLoggedIn()
|
||||||
|
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the user is not logged in, then switch to the login page
|
// 如果用户未登录,则跳转到登录页
|
||||||
const loginRoute: RouteKey = 'login'
|
const loginRoute: RouteKey = 'login'
|
||||||
const query = getRouteQueryOfLoginRoute(to, routeStore.routeHome)
|
const query = getRouteQueryOfLoginRoute(to, routeStore.routeHome)
|
||||||
|
|
||||||
@ -118,11 +126,11 @@ async function initRoute(to: RouteLocationNormalized): Promise<RouteLocationRaw
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!routeStore.isInitAuthRoute) {
|
if (!routeStore.isInitAuthRoute) {
|
||||||
// initialize the auth route
|
// 初始化权限路由
|
||||||
await routeStore.initAuthRoute()
|
await routeStore.initAuthRoute()
|
||||||
|
|
||||||
// the route is captured by the "not-found" route because the auth route is not initialized
|
// 由于权限路由未初始化,路由被“未找到”路由捕获
|
||||||
// after the auth route is initialized, redirect to the original route
|
// 权限路由初始化后,重定向到原始路由
|
||||||
if (isNotFoundRoute) {
|
if (isNotFoundRoute) {
|
||||||
const rootRoute: RouteKey = 'root'
|
const rootRoute: RouteKey = 'root'
|
||||||
const path = to.redirectedFrom?.name === rootRoute ? '/' : to.fullPath
|
const path = to.redirectedFrom?.name === rootRoute ? '/' : to.fullPath
|
||||||
@ -140,13 +148,13 @@ async function initRoute(to: RouteLocationNormalized): Promise<RouteLocationRaw
|
|||||||
|
|
||||||
routeStore.onRouteSwitchWhenLoggedIn()
|
routeStore.onRouteSwitchWhenLoggedIn()
|
||||||
|
|
||||||
// the auth route is initialized
|
// 权限路由已初始化
|
||||||
// it is not the "not-found" route, then it is allowed to access
|
// 如果不是“未找到”路由,则允许访问
|
||||||
if (!isNotFoundRoute) {
|
if (!isNotFoundRoute) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
// it is captured by the "not-found" route, then check whether the route exists
|
// 如果被“未找到”路由捕获,则检查路由是否存在
|
||||||
const exist = await routeStore.getIsAuthRouteExist(to.path as RoutePath)
|
const exist = await routeStore.getIsAuthRouteExist(to.path as RoutePath)
|
||||||
const noPermissionRoute: RouteKey = '403'
|
const noPermissionRoute: RouteKey = '403'
|
||||||
|
|
||||||
@ -162,7 +170,7 @@ async function initRoute(to: RouteLocationNormalized): Promise<RouteLocationRaw
|
|||||||
}
|
}
|
||||||
|
|
||||||
function handleRouteSwitch(to: RouteLocationNormalized, from: RouteLocationNormalized, next: NavigationGuardNext) {
|
function handleRouteSwitch(to: RouteLocationNormalized, from: RouteLocationNormalized, next: NavigationGuardNext) {
|
||||||
// route with href
|
// 外链路由
|
||||||
if (to.meta.href) {
|
if (to.meta.href) {
|
||||||
window.open(to.meta.href, '_blank')
|
window.open(to.meta.href, '_blank')
|
||||||
|
|
||||||
|
|||||||
2
apps/admin/src/typings/vite-env.d.ts
vendored
2
apps/admin/src/typings/vite-env.d.ts
vendored
@ -79,6 +79,8 @@ declare namespace Env {
|
|||||||
* - Dynamic: the auth routes is generated in back-end
|
* - Dynamic: the auth routes is generated in back-end
|
||||||
*/
|
*/
|
||||||
readonly VITE_AUTH_ROUTE_MODE: 'static' | 'dynamic'
|
readonly VITE_AUTH_ROUTE_MODE: 'static' | 'dynamic'
|
||||||
|
/** Whether to enforce login */
|
||||||
|
readonly VITE_AUTH_ROUTE_FORCE_LOGIN?: CommonType.YesOrNo
|
||||||
/**
|
/**
|
||||||
* The home route key
|
* The home route key
|
||||||
*
|
*
|
||||||
|
|||||||
Reference in New Issue
Block a user