vue实现路由权限控制,vue根据权限动态路由
本文主要介绍Vue3纯前端实现Vue路由授权的相关信息。通过示例代码非常详细,对大家学习或使用Vue3有一定的参考价值。有需要的朋友可以参考一下。
目录
前言RBAC模型代码实现登录菜单信息的动态路由筛选汇总
前言
在开发管理后台,会有多个角色登录。成功登录后,不同的角色会显示不同的菜单路径。这就是我们通常所说的动态路由授权。实现路由授权的方案有很多。比较常用的有前端使用addRoutes(V3版改为addRoute)动态挂载路由和服务器返回可访问路由菜单。今天主要是从前端的角度来实现路由权限的功能。
RBAC模型
前端路由授权主要基于RBAC模型。
基于角色的访问控制(RBAC)是基于角色的访问控制。通过将用户与角色相关联以及将权限与角色相关联,用户被间接授予权限。
代码实现
登录
首次登录。成功登录后,服务器会返回用户的登录角色、令牌和用户信息。用户,例如:角色:[admin]。我们通常会将这些信息保存在Vuex中。
常量登录=()={
ruleFormRef.value?validate((valid: boolean)={
如果(有效){
store . dispatch( user module/log in ,{.帐户表单})
}否则{
console.log(错误提交!)
}
})
}
信息存储在Vuex中:
异步登录({ commit },有效负载:IRequest) {
//登录获取令牌
const { data }=await accountLogin(有效负载)
提交( SET_TOKEN ,data.token)
localCache.setCache(token ,data.token)
//获取用户信息
const userInfo=await get userInfo(data . id)
提交( SET_USERINFO ,userInfo.data)
localCache.setCache(userInfo ,userInfo.data)
router.replace(/)
},
服务器返回令牌:
从服务器返回用户信息:
菜单信息
菜单信息有两种,一种是默认的route constantRoutes,即所有人都可以访问的页面,不需要通过用户角色来判断,比如登录、404、主页等。还有动态路由asyncRoutes,用于放置带权限的路由(roles属性)。这部分路线需要访问权限。最后我们会根据用户在动态路由中的角色筛选出可以访问的动态路由列表。
我们在router/index.ts中写入了默认路由和动态路由
从“vue-router”导入{ createRouter,createWebHashHistory,RouteRecordRaw }
const Layout=()=import( @/Layout )
/* *居民路线*/
export const constant routes:RouteRecordRaw[]=[
{
路径:“/login”,
名称:登录,
component:()=import( @/views/log in/index . vue ),
元:{
标题:“登录”,
隐藏:真
}
},
{
路径:“/”,
组件:布局,
重定向:“/分析/仪表板”,
名称:分析,
元:{
隐藏:假,
图标:“图标-主页”,
标题:“系统概述”
},
儿童:[
{
路径:“/分析/仪表板”,
名称:“仪表板”,
组件:()=import( @/views/analysis/dashboard/dashboard . vue ),
Meta: {title:商品统计,hidden: false}
},
{
路径:“/分析/概述”,
名称:概述,
component:()=import( @/views/analysis/overview/overview . vue ),
Meta: {title:核心技术,hidden: false}
}
]
},
{
路径:“/产品”,
组件:布局,
重定向:“/产品/类别”,
名称:产品,
元:{
隐藏:假,
图标:“图标-推剪”,
标题:“商品中心”
},
儿童:[
{
路径:“/产品/类别”,
名称:“类别”,
component:()=import( @/views/product/category/category . vue ),
Meta: {title:商品类别,hidden: false}
},
{
路径:/产品/商品,
名称:货物,
component:()=import( @/views/product/goods/goods)。vue’),
元:{标题: 商品信息,隐藏:false }
}
]
},
{
路径:"/故事",
组件:布局,
重定向:"/故事/聊天",
名称:"故事",
元:{
隐藏:假,
图标:图标-小溪,
标题: 随便聊聊
},
儿童:[
{
路径:/故事/聊天,
名称:"故事",
组件:()=import( @/views/story/chat/chat)。vue’),
元:{标题: 你的故事,隐藏:false }
},
{
路径:"/文章/列表",
名称:列表,
组件:()=import( @/views/story/list/list。vue’),
元:{标题: 故事列表,隐藏:false }
}
]
},
{
路径:"/404",
组件:()=import(@/views/404.vue ),
元:{
标题:"未找到",
隐藏:真
}
},
{
路径:"/:pathMatch(.*)*,
重定向:"/404",
元:{
隐藏:真实,
标题:"未找到"
}
}
]
/**
* 动态路由
* 用来放置有权限(角色属性)的路由
* 必须带有名字属性
*/
导出常量异步路由:RouteRecordRaw[]=[
{
路径:"/系统",
组件:布局,
重定向:"/系统/部门",
名称:系统,
元:{
隐藏:假,
图标:"图标-摄志",
标题: 系统管理
},
儿童:[
{
路径:"/系统/部门",
名称:部门,
组件:()=导入( @/视图/系统/部门/部门。vue’),
元:{标题: 部门管理,隐藏:假,角色:[admin] }
},
{
路径:"/系统/菜单",
名称:菜单,
component:()=import( @/views/system/menu/menu)。vue’),
元:{标题: 菜单管理,隐藏:假,角色:[admin] }
},
{
路径:"/系统/角色",
名称:"角色",
组件:()=导入( @/视图/系统/角色/角色)。vue’),
元:{标题: 角色管理,hidden: false,role: [editor] }
},
{
路径:"/系统/用户",
姓名:用户,
组件:()=导入( @/视图/系统/用户/用户。vue’),
元:{标题: 用户管理,hidden: false,role: [editor] }
}
]
}
]
const router=createRouter({
history: createWebHashHistory(),
路线:constantRoutes
})
导出默认路由器
我们将系统管理这个菜单作为动态路由部分,里面的子菜单自指的属性下都分配有一个访问权限的作用属性,我们需要将作用属性和用户角色去匹配是否用户具有访问权限。
动态路由筛选
思路:
我们登录得到了用户角色作用和写好路由信息(分为默认路由列表和动态路由列表),之后我们需要做的就是通过用户角色作用去匹配动态路由列表里面每个子路由的作用属性,得到能够访问的动态路由部分,将默认路由和我们得到的动态路由进行拼接这样我们就得到了用户能够访问的完整前端路由,最后使用增加走线将完整路由挂载到路由器上。
有了这样一个比较清晰的思路,接下来我们就来尝试着实现它。
我们可以将这块的逻辑也放在状态管理里面,在商店/模块下新建一个permission.ts文件。
首先我们需要写一个方法去判断用户是否具有访问单个路由的权限:
/**
* 判断用户是否有权限访问单个路由
*角色:用户角色
*路线:访问的路由
*/
const有权限=(roles:string[],route: any)={
如果(路线。元路由。meta。角色){
返回roles.some((role)={
if (route.meta?角色!==未定义){
返回路线。meta。角色。包括(角色)
}否则{
返回错误的
}
})
}否则{
返回真实的
}
}
实现的核心是route.meta.roles.includes(角色),即路由的角色是否包含了用户的角色,包含了就可以访问,否则不能。
对用户角色进行一些遍历主要是用户的角色可能存在多个,如:[admin , editor]。
这样我们就实现了单个路由访问权限的筛选,但是动态路由列表是一个数组,每个一级路由下可能有二级路由、三级路由甚至更多,这样我们就需要用到递归函数进行筛选:
/**
* 筛选可访问的动态路由
*角色:用户角色
*路线:访问的动态列表
*/
const filterasyncproutes=(routes:RouteRecordRaw[],roles: string[])={
const res: RouteRecordRaw[]=[]
routes.forEach((route)={
const r={.路线}
if (hasPermission(roles,r)) {
if (r.children) {
r。children=filterasyncproutes(r . children,roles)
}
资源推送(r)
}
})
返回资源
}
这样,通过调用过滤速度这个函数,然后传入utes:动态路由列表,角色:用户角色两个参数就能得到我们能访问的动态路由了。
然后我们将筛选得到的动态路由和默认路由通过联结合并多个字符串拼接得到完整可访问路由,最后通过增加走线挂载。
我们将以上代码逻辑整理到sion.ts里:
从" vuex "导入{模块}
从“vue路由器"导入{ RouteRecordRaw }
从"@/路由器"导入{ constantRoutes,asyncRoutes }
从导入{ IRootState }./类型
从@/路由器导入路由器
/**
* 判断用户是否有权限访问单个路由
*角色:用户角色
*路线:访问的路由
*/
const有权限=(roles:string[],route: any)={
如果(路线。元路由。meta。角色){
返回roles.some((role)={
if (route.meta?角色!==未定义){
返回路线。meta。角色。包括(角色)
}否则{
返回错误的
}
})
}否则{
返回真实的
}
}
/**
* 筛选可访问的动态路由
*角色:用户角色
*路线:访问的动态列表
*/
const filterasyncproutes=(routes:RouteRecordRaw[],roles: string[])={
const res: RouteRecordRaw[]=[]
routes.forEach((route)={
const r={.路线}
if (hasPermission(roles,r)) {
if (r.children) {
r。children=filterasyncproutes(r . children,roles)
}
资源推送(r)
}
})
返回资源
}
接口IPermissionState {
路线:RouteRecordRaw[]
dynamicRoutes: RouteRecordRaw[]
}
导出常量路由模块:ModuleIPermissionState,IRootState={
命名空间:对,
状态:{
路线:[],
动态路由:[]
},
getter:{ },
突变:{
SET_ROUTES(state,routes) {
state.routes=路线
},
SET_DYNAMICROUTES(状态,路线){
state.dynamicRoutes=路线
}
},
动作:{
generateRoutes({ commit },{ roles }) {
//访问路由:筛选出的动态路由
const访问的路由=filterasyncproutes(异步路由,角色)
//将访问路由和默认路由康斯坦特卢特斯拼接得到完整可访问路由
commit(SET_ROUTES),常量路由。concat(接入路由))
提交( SET_DYNAMICROUTES ,accessedRoutes)
//通过增加走线将路由挂载到路由器上
访问的路线。foreach((路由)={
router.addRoute(路由)
})
}
}
}
这样就实现了所有代码逻辑。有个问题,添加路由应该何时调用,在哪里调用?
登录后,获取用户的权限信息,然后筛选有权限访问的路由,再调用增加走线添加路由。这个方法是可行的。但是不可能每次进入应用都需要登录,用户刷新浏览器又要登录一次。所以增加走线还是要在全局路由守卫里进行调用。
我们在路由器文件夹下创建一个permission.ts用于写全局路由守卫相关逻辑:
从@/路由器导入路由器
从“vue路由器"导入{ RouteLocationNormalized }
从" @/实用程序/缓存"导入本地缓存
从"进展"导入n进展
导入 nprogress/nprogress.css
从" @/商店"导入商店
n进展。配置({ show spinner:false })
常数白名单=[/login]
路由器。每个之前(
异步(
to: RouteLocationNormalized,
出发地:RouteLocationNormalized,
下一个:任何
)={
document.title=to .元标题作为字符串
const token:string=local cache . get cache( token )
NProgress.start()
//确定用户是否登录。
if (token) {
if (to.path===/login) {
//如果已经登录,准备进入登录页面,重定向到首页。
下一步({路径:/ })
NProgress.done()
}否则{
const roles=store . state . user module . roles
store . dispatch( routes module/generate routes ,{ roles })
//确保添加路由已完成
//Set replace: true,这样导航就不会留下历史。
下一个({.到,替换:true })
//下一个()
}
}否则{
//如果没有令牌
if(白名单.包含(收件人路径)){
//如果在免登录白名单里,直接输入。
下一个()
}否则{
//其他没有访问权限的页面将被重定向到登录页面
下一步(/login )
NProgress.done()
}
}
}
)
router.afterEach(()={
NProgress.done()
})
这样就完成了完整的路由许可功能。我们可以做一个验证:
动态路由
我们登录的用户角色是roles: [editor],动态路由是系统管理菜单,其中有四个子路由对应角色。一般情况下,我们可以在系统管理菜单下进入角色管理和用户管理。
渲染菜单界面
选定的动态路由
没问题!
总结
前端动态路由基于RBAC,可访问的路由由用户角色筛选出来,安装在路由器上。这种实现的缺点是菜单信息写在前端,以后需要修改编译显示的文字或者权限信息。
关于Vue路由权的Vue3纯前端实现的这篇文章到此为止。更多关于Vue3纯前端实现路权的信息,请搜索我们之前的文章或者继续浏览下面的相关文章。希望大家以后能多多支持我们!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。