详解利用 Vue.js 实现前后端分离的RBAC角色权限管理

前端之家收集整理的这篇文章主要介绍了详解利用 Vue.js 实现前后端分离的RBAC角色权限管理前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

项目背景:物业管理后台,不同角色拥有不同权限

采用技术:Vue.js + Vuex + Element UI

实现 RBAC 权限管理需要后端接口支持,这里仅提供前端解决方案。

代码篇幅较大,对代码进行了删减,文中 “...” 即为省略的一部分代码

大致思路:

首先登录成功后,从后台拉取用户当前可显示菜单和可用权限列表,分别将其存入 store 的 nav(菜单导航) 和 auth(用户可用权限) 中,在用户切换路由时,判断是否存在 auth ,如果不存在,则重新获取,判断当前访问地址 to.Meta.alias 是否在用户可用权限列表中,如果不存在,则提示无权限,否则进入路由。

1. 路由与侧边菜单分离

侧边菜单相关代码 Main.vue

2. 路由切换前进行鉴权

路由定义的部分代码,对每个路由添加Meta 属性,用于鉴权。

这里 component 采用了异步引入的方式。

定义路由

import ('@/views/System/Organization.vue'),name: '组织结构',// requiresAuth 用于确认此地址是否需要验证 // alias 用于获取后端返回rbac权限对应的前端路由地址和导航菜单图标 Meta: {requiresAuth: true,alias: 'Pmsadmin/Oragnize/list'} },{ path: '/system/user',component: () => import ('@/views/System/User.vue'),name: '人员管理',redirect: '/system/user/index',children: [ { path: '/system/user/index',component: () => import ('@/views/System/UserList.vue'),name: '职员列表',Meta: {requiresAuth: true,alias: 'Pmsadmin/Admin/list'} } ] },{ path: '/system/auth',component: () => import ('@/views/System/Auth.vue'),name: '角色管理',alias: 'Pmsadmin/Role/list'} } ] } // ...

路由钩子 beforeEach

{ document.title = `${configs.title} - ${to.name}`; const {hasAuth,auth} = store.state.user; // 未拿到权限,则获取 if (!hasAuth) { store.dispatch('getUserAuth'); console.log('重新获取用户权限'); // next(); } // 如果未登录跳转 if (window.localStorage.getItem('IS_LOGIN') === null && to.path !== '/login') { console.log('未登录状态'); next({ path: '/login',query: {redirect: to.fullPath} // 将跳转的路由path作为参数,登录成功后跳转到该路由 }) } else { // 需要鉴权的路由地址 console.log(to,auth.indexOf(to.Meta.alias),auth); if (to.Meta.requiresAuth) { if (auth.indexOf(to.Meta.alias) > -1) { console.log('有权限进入'); next(); } else { if(auth.length > 0) { Message.error({ message: '当前用户权限不足,无法访问',showClose: true,}); } else { next(); } } } else { next(); } } });

在 Vuex 的 state 中,定义好 nav 对象

登录用户信息 const user = { name: '',// 用户名 avatar: '',// 用户头像 auth: [],// 用户权限 hasAuth: false // 是否已经加载用户权限 }; // 导航菜单 const nav = [];

通过 action 异步获取数据

{ const res = await http.post('YOUR_URL',{}); if (res === null) return; console.log('getUserAuth',res.param); commit('SET_USER_AUTH',res.param.auth); commit('SET_SIDE_NAV',res.param.nav); };

Vuex 中的 mutation 的相关代码

{ state.user.auth = auth.concat('欢迎使用'); state.user.hasAuth = true; }; // 设置导航菜单 const SET_SIDE_NAV = (state,nav) => { // 导航菜单 let _nav = [{ name: '欢迎使用',url: "/main",iconCls: 'fa fa-bookmark' }]; // 权限菜单对应的路由地址 const route = { "系统管理": {iconCls: 'fa fa-archive',url: ''},"Pmsadmin/Oragnize/list": {iconCls: '',url: '/system/organization'},"Pmsadmin/Admin/list": {iconCls: '',url: '/system/user/index'},"Pmsadmin/Role/list": {iconCls: '',url: '/system/auth'},"Pmsadmin/Log/record": {iconCls: '',url: '/system/logs'},"项目管理": {iconCls: 'fa fa-unlock-alt',"Pmsadmin/Project/list": {iconCls: '',url: '/project/list/index'},"Pmsadmin/House/list": {iconCls: '',url: '/project/house'},"Pmsadmin/Pack/list": {iconCls: '',url: '/project/pack'},"广告位": {iconCls: 'fa fa-edit',"Pmsadmin/Place/list": {iconCls: '',url: '/adsplace/list'},"投诉建议": {iconCls: 'fa fa-tasks',"Pmsadmin/Scategory/list": {iconCls: '',url: '/complain/type'},"Pmsadmin/Complain/list": {iconCls: '',url: '/complain/list'},"Pmsadmin/Suggest/list": {iconCls: '',url: '/complain/suggestion'},"报事报修": {iconCls: 'fa fa-user',"Pmsadmin/Rcategory/list": {iconCls: '',url: '/rcategory/type'},"Pmsadmin/Rcategory/info": {iconCls: '',url: '/rcategory/public'},"Pmsadmin/Repair/list": {iconCls: '',url: '/rcategory/personal'},"便民服务": {iconCls: 'fa fa-external-link',"Pmsadmin/Bcategory/list": {iconCls: '',url: '/bcategory/type'},"Pmsadmin/Service/list": {iconCls: '',url: '/bcategory/list'},"首座推荐": {iconCls: 'fa fa-file-text',"Pmsadmin/stcategory/list": {iconCls: '',url: '/stcategory/type'},"Pmsadmin/Store/list": {iconCls: '',url: '/stcategory/list'},"招商租赁": {iconCls: 'fa fa-leaf',"Pmsadmin/Bussiness/list": {iconCls: '',url: '/bussiness/list'},"Pmsadmin/Company/list": {iconCls: '',url: '/bussiness/company'},"Pmsadmin/Question/list": {iconCls: '',url: '/bussiness/question'},"停车找车": {iconCls: 'fa fa-ra',"Pmsadmin/Cplace/list": {iconCls: '',url: '/cplace/cmanage'},"Pmsadmin/Clist/list": {iconCls: '',url: '/cplace/clist'},"Pmsadmin/Cquestion/list": {iconCls: '',url: '/cplace/cquestion'},}; for (let key in nav) { let item = nav[key]; let _temp = {}; let subItems = []; // 二级菜单临时数组 if (item.children && item.children.length > 0) { // 二级菜单 item.children.forEach(subItem => { subItems.push(Object.assign({},{ name: subItem.name || '',url: route[subItem.url].url || '',iconCls: route[subItem.url].iconCls || '',})) }); // 一级菜单 _temp = Object.assign({},{ name: item.name || '',url: item.url || '',iconCls: route[item.name].iconCls || '',children: subItems.slice(0) }); _nav.push(_temp); } } state.nav = _nav; };

3. 后端接口返回内容

查询成功!","param": { "nav": { "1": { "name": "系统管理","url": "","children": [ { "name": "组织结构","url": "Pmsadmin/Oragnize/list" },{ "name": "人员管理","url": "Pmsadmin/Admin/list" },{ "name": "角色管理","url": "Pmsadmin/Role/list" },{ "name": "日志管理","url": "Pmsadmin/Log/record" } ] },"61": { "name": "广告位","children": [ { "name": "广告位列表","url": "Pmsadmin/Place/list" } ] } },"auth": [ "系统管理","Pmsadmin/Oragnize/list","Pmsadmin/Admin/list","Pmsadmin/Role/list","Pmsadmin/Log/record","广告位","Pmsadmin/Place/list" ] } }

存在的问题

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程之家。

猜你在找的Vue相关文章