加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

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

发布时间:2020-12-17 02:47:46 所属栏目:百科 来源:网络整理
导读:项目背景:物业管理后台,不同角色拥有不同权限 采用技术:Vue.js + Vuex + Element UI 实现 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 对象

通过 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. 后端接口返回内容

存在的问题

  • 新增 修改 删除 按钮还无法实现根据用户权限控制其显示
  • 代码上还存在着不足,期待大神能够有更优的解决方案。

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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读