在使用 vue
做中后台管理系统项目时,我们经常会涉及到权限管理,即对菜单树进行权限控制,由于不同框架本身的一些特性,通常实现权限功能的方式也大不相同。
本文就 vue
项目来介绍一种菜单树的权限管理方式。
前言
对于 vue
项目来说,我们通常会将 菜单树
和 路由表
进行关联,也就是说,最终的菜单树
会根据 完整的路由表
生成。
这里 完整的路由表
可以分为:静态路由
和 动态路由
这两部分。
- 静态路由
指的是,用户可正常访问的路由,诸如 /login
、/404
、/about
等。这些路由信息不会与菜单树关联。
- 动态路由
指的是,有对应权限的用户才可以访问,这些路由信息会与菜单树进行关联。
那么,最终的菜单树
又可以如何确定呢?
我们可以借鉴像 vue-element-admin 这样的后台模板框架实现菜单树的思路,对 完整的路由表
中路由对象 hidden
属性为 false
的项作为一个菜单树节点。
1 | [ |
资源管理
为了做到对页面菜单项的灵活控制,我们的项目中应该有一个叫做 资源管理
的页面。该页面主要的作用是可以很方便的 新增、修改、删除
一个权限菜单项。
而该资源菜单树的每一个菜单项可以使用一个唯一的 权限编码(code)
与动态路由对象进行关联。
也就是说,后台存储的是一个有 权限编码(code)
信息的菜单树形数据结构,如下所示:
1 |
|
如上数据结构所示,code
属性表示该菜单节点的权限编码,name
属性表示该菜单节点的名称,当然,你也可以加入一些其他的可控字段。
动态路由定义
我们已经维护好了一份资源菜单树,那么,接下来的工作就是对每个 权限编码
去定义对应的路由对象信息,这样,我们就可以在后面通过 遍历权限菜单树 去生成一份动态路由表出来。
前端定义的 动态路由 类似于下面这样:
1 | const dynamicRoutes = { |
根据权限树生成路由表
权限树数据 和 动态路由定义已经处理好了,现在,我们就要根据这两份数据生成 vue-router
可用的路由表数据了。
可以使用如下函数进行生成:
1 | // 根据权限树生成可用的路由表 |
插入到路由表中
最后,我们可以使用 addRoutes
方法将生成的路由表数据添加到路由中,这样,路由、权限和菜单
就进行了很好的关联,后续对菜单项的控制也会非常方便。
1 | // ... |
上面的 routes
就是通过比对权限后生成的路由表数据了。
用户角色管理
通常,我们的权限是绑定到角色的,不同的角色有不同的权限,所以,我们可以在 用户角色管理
模块去绑定对应的菜单权限。
页面如何设计就看你自己了。
动态路由与后台关联的另一种方式
在第一种方式中,当将菜单权限赋予某个角色后,那么,该角色对于的菜单树结构就已经成型了,只不过需要将菜单 权限code
替换为真正的路由对象
。再在适合的时机插入到路由表中。
这里还有另一种实现方式。我们将完整的动态路由同步到后台数据库,除了路由对象中的 component
字段变为 String
类型以外,该动态路由没有任务其他特殊之处。
1 | [ |
如上动态路由所示,我们可以看到两个比较特殊的地方,第一个是 component
字段,第二个是 meta
中的 roles
字段。他们有什么意义呢?
component字段
该字段表示路由对象所映射的组件。由于我们需要将整个动态路由表存储到后台数据库,所以,原先的 component
设置方式不再适用,这里我们该用字典关联的方式来解决。我们会有这样一个文件,存储着动态路由中的所有动态组件。
1 | // dynamicRoutesMap.js |
roles字段
该字段表示路由对象所关联的角色有哪些。也就是说,只要某个路由对象中的 roles
信息中的角色是当前用户所拥有的,那么该路由对象就该被显示出来。当然,roles
字段是后台动态追加进去的,可在 用户角色管理 页面进行处理。
如何过滤出当前用户有权访问的路由表
获取当前用户信息
我们首先需要获取当前用户信息,即,当前用户拥有的角色信息。
1 | { |
如上所示,张三
同时拥有 role1
、role2
和 role3
这三个角色。
获取动态路由信息
1 | [ |
如上所示,这一个经过后台处理的含有完整 roles
信息的动态路由表。每个路由对象都有对应的 roles
信息。表示该路由对象对哪些角色可见。
经过过滤处理后,实际生成的动态路由表示这样的。
1 | [ |
因为,当前用户没有 admin
角色权限,所以 资源管理 这个路由对象被剔除。
最后,我们依然会使用 addRoutes
方法将生成的 动态路由表 插入到路由表中,菜单树,也会根据动态路由渲染出来。