Vue2.0用户权限控制解决方案的示例

Vue-Access-Control是一套基于Vue/Vue-Router/axios 实现的前端用户权限控制解决方案,通过对路由、视图、请求三个层面的控制,使开发者可以实现任意颗粒度的用户权限控制。

安装

版本要求

Vue 2.0x

Vue-router 3.x

获取

git:git clone https://github.com/tower1229/Vue-Access-Control.git

npm:npm i vue-access-control

运行

//开发 npm run dev //构建 npm build

概述

整体思路

会话开始之初,先初始化一个只有登录路由的Vue实例,在根组件created钩子里将路由定向到登录页,用户登录成功后前端拿到用户token,设置axios实例统一为请求headers添加{"Authorization":token}实现用户鉴权,然后获取当前用户的权限数据,主要包括路由权限和资源权限,之后动态添加路由,生成菜单,实现权限指令和全局权限验证方法,并为axios实例添加请求拦截器,至此完成权限控制初始化。动态加载路由后,路由组件将随之加载并渲染,而后展现前端界面。

为解决浏览器刷新路由重置的问题,拿到token后要将其保存到sessionStorage,根组件的created钩子负责检查本地是否已有token,如果有则无需登录直接用该token获取权限并初始化,如果token有效且当前路由有权访问,将加载路由组件并正确展现;若当前路由无权访问将按路由设置跳转404;如果token失效,后端应返回4xx状态码,前端统一为axios实例添加错误拦截器,遇到4xx状态码执行退出操作,清除sessionStorage数据并跳转到登录页,让用户重新登录。

最小依赖原则

Vue-Access-Control的定位是单一领域解决方案,除了Vue/Vue-Router/axios之外没有其他依赖,理论上可以无障碍的应用到任何有权限控制需求的Vue项目中,项目基于webpack 模板开发构建,大多数新项目可以直接基于检出代码继续开发。需要说明的是,项目额外引入的和 CryptoJS仅用于开发演示界面,他们不是必须且与权限控制毫无关系,项目应用中可以自行取舍。

目录结构

src/ |-- api/ //接口文件 | |-- index.js //输出通用axios实例 | |-- account.js //按业务模块组织的接口文件,所有接口都引用./index提供的axios实例 |-- assets/ |-- components/ |-- router/ | |-- fullpath.js //完整路由数据,用于匹配用户的路由权限得到实际路由 | `-- index.js //输出基础路由实例 |-- views/ |-- App.vue ·-- main.js

数据格式约定

路由权限数据必须是如下格式的对象数组,id和parent_id相同的两个路由具有上下级关系,如果希望使用自定义格式的路由数据,需要修改路由控制的相关实现,详见路由控制

[ { "id": "1", "name": "菜单1", "parent_id": null, "route": "route1" }, { "id": "2", "name": "菜单1-1", "parent_id": "1", "route": "route2" } ]

资源权限数据必须是如下格式的对象数组,每个对象代表一个RESTful请求,支持带参数的url,具体格式说明见请求控制

[ { "id": "2c9180895e172348015e1740805d000d", "name": "账号-获取", "url": "/accounts", "method": "GET" }, { "id": "2c9180895e172348015e1740c30f000e", "name": "账号-删除", "url": "/account/**", "method": "DELETE" } ]

路由控制

路由控制包括动态注册路由和动态生成菜单两部分。

动态注册路由

最初实例化的路由仅包括登录和404两个路径,我们期待完整的路由是这样的:

[{ path: '/login', name: 'login', component: (resolve) => require(['../views/login.vue'], resolve) }, { path: '/404', name: '404', component: (resolve) => require(['../views/common/404.vue'], resolve) }, { path: 'https://www.jb51.net/', name: '首页', component: (resolve) => require(['../views/index.vue'], resolve), children: [{ path: '/route1', name: '栏目1', meta: { icon: 'icon-channel1' }, component: (resolve) => require(['../views/view1.vue'], resolve) }, { path: '/route2', name: '栏目2', meta: { icon: 'ico-channel2' }, component: (resolve) => require(['../views/view2.vue'], resolve), children: [{ path: 'child2-1', name: '子栏目2-1', meta: { }, component: (resolve) => require(['../views/route2-1.vue'], resolve) }] }] }, { path: '*', redirect: '/404' }]

那么接下来就需要获取首页以及其子路由们,思路是事先在本地存一份整个项目的完整路由数据,然后根据用户权限对完整路由进行筛选。

筛选的实现思路是先将后端返回的路由数据处理成如下哈希结构:

let hashMenus = { "/route1":true, "/route1/route1-1":true, "/route1/route1-2":true, "/route2":true, ... }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/ppzff.html