项目中权限的实现方式:

1 创建 vue 实例的时候将 vue-router 挂载,但这个时候 vue-router只挂载一些登录或者不用权限的公用的页面。

2 当用户登录后,获取用 role,将 role 和路由表每个页面的需要的权限作比较,生成最终用户可访问的路由表。

3 调用 router.addRoutes(store.getters.addRouters) 添加用户可访问的路由。

4 使用 vuex管理路由表,根据 vuex 中可访问的路由渲染侧边栏组件。

路由

路由代码在/src/router/index.js中,有两种:

  1. constantRoutes: 代表那些不需要动态判断权限的路由,如登录页、404、等通用页面。
  2. asyncRoutes: 代表那些需求动态判断权限并通过 addRoutes 动态添加的页面。

代码中的roles标签记录了可访问此路由的所有角色。如代码中的‘/permission’路由,只有‘admin’或’editor’的角色可以访问。

1
2
3
4
5
6
7
8
9
10
11
12
//index.js
{
path: '/permission',
component: Layout,
redirect: '/permission/page',
alwaysShow: true, // will always show the root menu
name: 'Permission',
meta: {
title: 'Permission',
icon: 'lock',
roles: ['admin', 'editor'] //
},

权限验证

“路由层面权限的控制代码都在 <@/permission.js 中,如果想修改逻辑,直接在适当的判断逻辑中 next() 释放钩子即可。”

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//`@/permission.js` 代码片段
try {
//第一步,获取用户角色
const { roles } = await store.dispatch('user/getInfo')

//第二步:通过角色获取其可访问的路由表
const accessRoutes = await store.dispatch('permission/generateRoutes', roles)

//第三步:通过 router.addRoutes 动态挂载到 router 上。
router.addRoutes(accessRoutes)

// hack方法 确保addRoutes已完成
next({ ...to, replace: true })
}

生成可访问路由表的相关代码在src/modules/permission.js文件中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
//通过用户的权限和之前在router/index.js里面asyncRouterMap的每一个页面所需要的权限做匹配,最后返回一个该用户能够访问路由有哪些。
const actions = {
generateRoutes({ commit }, roles) {
return new Promise(resolve => {
let accessedRoutes
//在路由表中,不是所有页面都设置了admin权限,这里(store/modules/permission.js)逻辑是如果是admin则返回所有页面。
// if (roles.includes('admin')) { //如果用户是admin,
// //新建数组
// var arr =[]
// //进行异步数组的过滤
// asyncRoutes.forEach((item)=>{
// if(item. hasOwnProperty('meta')){
// if(item.meta.hasOwnProperty('roles')){
// if(item.meta.roles.includes('admin')){
// //将含有admin角色的路由加入新数组
// arr.push(item)
// }
// }
// }
// })
// accessedRoutes = arr || []
// //accessedRoutes = asyncRoutes || [] //返回所有的页面
// } else { //如果不是,只返回可访问的页面
// accessedRoutes = filterAsyncRoutes(asyncRoutes, roles)
// }
accessedRoutes = filterAsyncRoutes(asyncRoutes, roles)
commit('SET_ROUTES', accessedRoutes)
resolve(accessedRoutes)
})
}
}

指令权限

封装了一个指令权限,能简单快速的实现按钮级别的权限判断。v-permission。比如:

1
<el-tag v-permission="['admin']">admin</el-tag>

有很多人一直在问关于按钮级别粒度的权限控制怎么做。我司现在是这样的,真正需要按钮级别控制的地方不是很多,现在是通过获取到用户的role之后,在前端用v-if手动判断来区分不同权限对应的按钮的。理由前面也说了,我司颗粒度的权限判断是交给后端来做的,每个操作后端都会进行权限判断。而且我觉得其实前端真正需要按钮级别判断的地方不是很多,如果一个页面有很多种不同权限的按钮,我觉得更多的应该是考虑产品层面是否设计合理。当然你强行说我想做按钮级别的权限控制,你也可以参照路由层面的做法,搞一个操作权限表。。。但个人觉得有点多此一举。或者将它封装成一个指令都是可以的。

参考:
手摸手,带你用vue撸后台 系列二(登录权限篇)

权限验证 | 文档