1.是什么:
RBAC(Role-Based Access control)权限模型 ,也就是基于角色的权限分配解决方案。
2.作用:
为了达成
不同的帐号登陆系统后能看到不同的页面,能执行不同的功能
的目标
业务中应用场景: 最常见于后台管理项目中,如新员工入职,会分配给他公司的内部网站账号,这个新员工登录公司后台网站,看到的内容和能操作的权限肯定和经理不同。
而如果一个公司有几万人,且职位等级森严,那么怎么分配权限就成了问题,甚至如再有人事调度,我本来刚进公司是普通员工,过了两年成了总经理,那么权限也自然要修改。
而RBAC便是这类问题的解决方案之一,目前也是比较流行的解决方案
3.权限模式图解
如下:
3.1 举例理解:
先给这名员工一个角色,然后设置角色的权限(如考勤、薪资管理),最后,员工就有了权限
小结:
一种基于角色的设计思想
- 给员工配置角色 (一个员工可以拥有多个角色)
- 给角色配置权限点 (一个角色可以有多个权限点)
员工只要有了角色之后,就自动拥有了角色绑定的所有权限
4.使用
基于RBAC权限设计思想,将整个权限功能划分为三个模块。分别是权限页,角色页、员工管理页。
第一步:设置权限页
这一步最重要的是给权限设置唯一的标识,后面做逻辑要用到
第二步:设置角色页
在这一步中,最重要的是设置角色的权限
第三步:员工管理页
在这一步中,最重要的是设置分配角色
小结:
到目前为止,我们实现了RBAC权限设计思想的各个环节,我们给员工分配了角色,给角色又分配了权限点,员工现在已经有了相对应的权限点,接下来我们就可以利用这些权限点做实际的权限控制
5.业务场景:
张三,新入职,将他的角色设置为普通职员,那么他的权限就已经自动设置完毕。因为普通职员这个角色已经在角色页面中配置权限了。也就是说权限的分配不是直接给张三,而是给了一个角色,这个角色叫做普通职员。
问题1:张三登录公司网站,看到的应该是自己的权限内能看到的内容,使用自己权限内的功能,而他的领导权限更大,看到的更多。所以如何实现不同的职位看到的不同内容?
问题2: 页面有个按钮叫"查看人员薪资情况",那么这种机密性质的按钮,只有具有该权限的角色才能点,没有这个权限的角色应该是看不到的,那么怎么该怎么样让有的人能看到这个按钮有的人隐藏呢?
知识铺垫:
addRoutes基本使用
格式
router.addRoutes([路由配置对象]) 或者: this.$router.addRoutes([路由配置对象])
作用:动态添加路由配置
为啥非要用这个啊? 你如果写死了,那么页面上的路由就是固定的,看到的菜单也是同样的。也就意味着全剧终,不用往下看了。
6.业务问题解决
相信以后不会遇到一毛一样的业务,但是大体实现的功能确是差不多的,所以列出业务中需要实现功能的思路,和容易遇到的问题的解决方法。
代码就不贴了,毕竟每个项目不一样。
7. 业务问题1: 动态生成菜单(不同的权限看到不同的菜单)
7.1 业务逻辑处理位置
大概率业务处理逻辑在路由守卫里面做,原因很简单,从登录页到首页,菜单的渲染不可能等你进去首页才渲染,应该在你登录到跳转到首页之间。
7.2 业务处理逻辑
概括:拿到总的路由数,拿到用户能访问的路由数,如果在总的路由里有那么就显示。
01.删除路由表中动态路由部分,使用addRoutes动态添加
02.引入动态路由表,改写成动态路由【这里特别注意,使用addRoutes并不能在菜单栏看到,只能通过浏览器手动输入路由地址,依旧可用,其实已经添加到我们的路由系统了】
03.将使用 addRoutes方法之后,路由数据保存起来,使用vuex。(全局组件可用数据,且修改响应式)
04.用总的路由数和使用addRoutes方法保存的路由数,做筛选,两个数据具有公共的留下,最后剩下的就是最终的路由表
8.按钮级控制
员工A和员工B都可以访问同一个页面(以员工管理为例),但是员工A可以导出excel,员工B就不可以导出excel
思路:
概括:以权限唯一标识作为查找条件,如果在路由权限数组中找到就显示,反之不显示。
用户登陆成功后,用户可以访问的按钮级别权限保存在数组中。而这个数据我们是保存在vuex中的,所以,就可以在项目的任意地方来中访问。
如果某个按钮上的标识在数组中出现,则可以显示出来
自定义指令注册格式:
// 注册一个全局自定义指令 `v-focus` Vue.directive('focus', { // 当被绑定的元素插入到 DOM 中时inserted会自动执行 inserted: function(el, binding) { // v-focus="'abc'" ===> binding.value = 'abc' console.log('focus.... binding', binding.value) // 聚焦元素 el.focus() } }) ------------------------------------------------------------------------------ // 注册一个全局自定义指令 `v-allow` Vue.directive('allow', { inserted: function(el, binding) { // 从vuex中取出points, const points = store.state.user.userInfo.roles.points // 如果points有binding.value则显示 if (points.includes(binding.value)) { // console.log('判断这个元素是否会显示', el, binding.value) } else { el.parentNode.removeChild(el) // el.style.display = 'none' } } })
使用格式
<input v-foucs="'xxxx'" /> --------------------------- v-allow="'import_employee'" //import_employee是设置的权限标识
9. bug --刷新页面时的bug修复
问题:
如果我们刷新浏览器,会发现跳到了404页面
对于addRoute添加的路由,在刷新时会白屏
原因:
现在我们的路由设置中的404页处在中间位置而不是所有路由的末尾了。
解决:
把404页改到路由配置的最末尾就可以了
路由是存在数组中的,用push方法加到最后
10. bug--退出登录时重置路由
问题:
退出后,再次登陆,发现菜单异常 (控制台有输出说路由重复)
原因:
退出时,并没有清空,再次登陆,又加了一次,所以有重复。
解决:
这个方法就是将路由重新实例化,相当于换了一个新的路由,之前加的路由
就不存在了,需要在登出的时候, 调用一下即可
// 重置路由 export function resetRouter() { const newRouter = createRouter() router.matcher = newRouter.matcher // 重新设置路由的可匹配路径 }