目前公司内部,基于 Vue 全家桶的项目还是比较多的。在入职公司后,刚好团队在开发内部的一个运营管理的 MIS 系统。在项目初期,对于系统的权限控制,比较粗糙。随着 MIS 系统的内容越来越多,对于系统的用户权限便不得不去进行限制区分了。
公司内部项目最初是采用的,先加载所有的路由,只在菜单上做了显示与隐藏,这个显而易见的风险就是研发人员可以通过拼接路由的形式,访问到本来没有权限访问的内容,这样的权限设置对于研发而言,形同虚设。但是,由于是内部系统,最初的这个方案,就一直延续下来了。随着 MIS 系统内容的丰富,许多核心的数据开始增加,以前的这种方案带来的风险,逐渐被放大。于是,针对权限控制这一方案,开始了自我探索。
iview-admin的路由权限
iview-admin采用的是挂载全部路由,然后在路由的全局守卫进行判断。router.js
1 | import Main from '@/views/Main.vue'; |
然后路由处理方法:
1 | import Vue from 'vue'; |
通过在全局守卫来进行判断,先判断用户是否登录,如果未登录,就跳转到登录页。根据cookie里数据,如果用户已登陆过,且要跳转的地址为登录页,则直接跳到 hone_index 页面。登录后,先判断路由是否包含 access 字段,该字段是用来针对用户进行权限控制权限使用的。如果路由中没有该字段,则表示该路由无需进行权限控制。如果路由进行了权限控制,则进行判断,有权限则进入,无权限则进入到 403 页面。
诚然这种方式,还是可以解决目前我们项目目前的问题,但是还是有问题的:
- 路由和菜单混合,因为有些路由不需要作为菜单显示,最后导致整个路由信息比较臃肿;
- 菜单文字和icon在前端维护,如需修改,需要重新部署上线;
- 每次跳转都需要在全局路由守护中进行判断
- 系统每次加载都需要挂载全部路由,对于无权限访问的路由,显然有点多余
vue-element-admin
github 上 star 数目较多的一个基于 element-ui 的后台管理系统 vue-element-admin。
1 | import Vue from 'vue' |
路由处理方法permission.js:
1 | ... |
相对于 iview-admin, vue-element-admin 的路由权限控制应该是相对更加成熟一点。对于不需要权限控制的路由,直接在 constantRouterMap 里设置好了,并在初始化时挂载到应用上了。对于需要根据用户访问的权限,可以通过 asyncRouterMap 中设置路由的权限,然后通过 addRoutes 动态挂在到 router 上。
当然作者还用了指令权限方式。
基于自有项目的解决方案
在结合自身的项目的特点以及需求的基础上,后来总结了一套符合自身的开发方案,反过来与已有的方案对比,感觉有共同的地方,也有与之不同的地方,总而言之,是目前最符合项目的方案吧。
同上 vue-element-admin 类似,也是讲无需权限控制的路由,在页面初始化时就进行了挂载。
1 | import Vue from 'vue'; |
另外还需一个组件文件(component.js):
1 | const home = () => import('../page/Home.vue'); |
路由和菜单权限通过服务端放回,在路由钩子函数(导航守卫)里进行操作:
1 | // 设置一个标志位用来标识是否需要从服务端获取菜单和路由权限 |
该方案与 vue-element-admin 方案有很大的类似的地方,不同的在于,我们的路由权限完全由服务端返回,所以不会存在用户能访问超过权限之外的页面的情况。
同时,该方案有一个最大的弊端,就是路由和组件名与后端是强耦合的,同时,有个待改进的地方,就是加入用户拥有某个菜单权限,用户直接在浏览器输入后,进入登录页再回跳到该页面(vue-element-admin已经实现了,我们的改造成本也不大^_^)。目前该方案已在内部项目中成功的实施了。后续再考虑下,是否有更好的优化方案。