权限部分在RBAC的权限控制基础上,实现了员工管理,权限管理,角色绑定和权限绑定等功能,让管理员用户可以通过将权限分配给角色后,角色分配用户实现权限控制,并通过动态路由和全局指令实现路由和按钮的权限控制。
下面具体说说:
一、什么是RBAC权限控制?
答案
:
RBAC
的权限模型,
RBAC(Role-Based Access control)
,也就是基于角色的权限分配解决方案,同角色有着相同的权限,
操作角色权限的同时
,
所有该角色的用户对应权限
,
就会同步更新。
二、说说菜单权限怎么做的?
大概分成下面几个步骤
- 1项目通过几个业务模块的配合生成对应的权限数据
async getUserInfo(ctx) {
// 调用获取用户信息的接口
const res = await getUserInfo()
// 获取用户头像
const info = await getUserDetailById(res.userId)
ctx.commit('setUserInfo', { ...res, ...info })
// 将个人权限数据返回
return res.roles
}
- 2把后端返回的权限数据和前端本地的路由做对比,得到过滤之后的有资格显示的路由数组
import { asyncRoutes } from '@/router'
if (!store.getters.userId) {
// 拿到菜单权限数据
const roles = await store.dispatch('user/getUserInfo')
// 做过滤处理
// 如果路由的name属性能在menus权限数据中找到代表可以访问
let filterRoutes = []
filterRoutes = asyncRoutes.filter(route => {
return roles.menus.includes(item.children[0].name)
})
console.log('根据权限过滤后的路由表为:',filterRoutes)
}
- 3调用路由核心方法router.addRoutes把路由数组加入到路由系统中
if (!store.getters.userId) {
// 拿到菜单权限数据
const roles = await store.dispatch('user/getUserInfo')
// 这里做权限控制
// 做过滤处理
// 如果路由的name属性能在menus权限数据中找到代表可以访问
let filterRoutes = []
filterRoutes = asyncRoutes.filter(route => {
return roles.menus.includes(item.children[0].name)
})
// 把动态路由添加到应用的路由系统里
router.addRoutes(filterRoutes)
}
- 4如果需要显示到左侧菜单里,可以配合vuex做,vuex存一份相同的数据,渲染左侧的菜单
1. 定义vuex管理菜单数据
// 导入静态路由
import { constantRoutes } from '@/router'
export default {
namespaced: true,
state: {
// 先以静态路由表作为菜单数据的初始值
menuList: [...constantRoutes]
},
mutations: {
setMenuList(state, asyncRoutes) {
// 将动态路由和静态路由组合起来
state.menuList = [...constantRoutes, ...asyncRoutes]
}
}
}
2. 提交setMenuList生成完整的菜单数据
if (!store.getters.userId) {
await store.dispatch('user/getUserInfo')
// 把动态路由添加到应用的路由系统里
router.addRoutes(asyncRoutes)
// 把动态路由数据交给菜单
store.commit('routeMenu/setMenuList', asyncRoutes)
}
3. 菜单生成部分改写使用vuex中的数据
routes() {
// 拿到的是一个完整的包含了静态路由和动态路由的数据结构
// return this.$router.options.routes
return this.$store.state.routeMenu.menuList
}
三、 按钮的权限又怎么做呢?
按钮的权限其实就是控制显示隐藏
思路就是通过后端返回的权限标识和按钮自身的标识code做对比,如果有资格就显示,否则就隐藏。这里根据思路我们可以封装一个全局指令,通过指令可以实现复用,就可以在需要控制的按钮身上进行指令绑定,从而控制按钮的显示也隐藏。
//定义全局指令
import Vue from 'vue'
import store from '@/store'
Vue.directive('checkBtn', {
inserted(el, binding) {
const { value } = binding
const hasPermission = store.state.user.userInfo.roles.points.includes(value)
if (!hasPermission) {
el.parentNode.removeChild(el)
// el.remove()
}
}
})
//使用全局指令
<!-- CKGZ -->
<el-button v-checkBtn="'CKGZ'">查看工资</el-button>
<!-- XGGZ -->
<el-button v-checkBtn="'XGGZ'">修改工资</el-button>