后台管理系统权限控制

发布时间 2023-11-21 00:02:29作者: yunChuans

菜单栏控制

实现思路

一般是后端返回菜单栏数组,前端根据数组动态创建菜单栏,这里以fe-backend-archive项目为例。使用elementui的 el-menu ,以及组件的递归调用,动态渲染菜单栏。

 <el-menu
        :default-active="defaultActive"
        background-color="#fff"
        text-color="#303133"
        active-text-color="#303133"
        unique-opened
        @select="handleSelect"
        :style="{ height: menuHeight + 'px' }"
      >
        <app-child
          v-for="item in menuData"
          :key="item.name"
          :item-data="item"
        ></app-child>
      </el-menu>

child

<el-menu-item v-if="itemData.subMenus == null" :index="itemData.url">
      <span v-if="itemData.icon" :class="['fa', itemData.icon, 'fa-ls']"></span>
      <span class="name"> {{ itemData.name }}</span>
 </el-menu-item>
    <el-submenu v-if="itemData.subMenus != null" :index="itemData.name">
      <template slot="title">
        <i v-if="itemData.icon" :class="['fa', itemData.icon, 'fa-ls']"></i>
        <span> {{ itemData.name }}</span>
      </template>
      <!--调用组件自身,循环item的children,实现递归  Number(itemData.index)-->
      <child
        v-for="(item) in itemData.subMenus"
        :key="item.name"
        :item-data="item"
      ></child>
    </el-submenu>

用户权限的控制

实现思路

  • 使用vuex存储用户的权限,每个页面需要的权限不一样,所以会有下面的结构。
state: {
    permission:{
            /home: ['archive:appoint:update','archive:appoint:read']
    }
} 
  • 需要一个接口,用于请求用户拥有的权限,用于和进入页面需要的权限做比对。
  • 基本逻辑在路由前置首位中完成,每进入新页面都需要判断用户有无权限。

具体代码实现

在路由meta中,有 enterPermission pagePermission, 两个权限字段,前者表示进入页面需要的权限,后者表示页面中的所有权限。

 {
    path: '/appoint',
    name: 'appoint',
    component: resolve => require(['@/pages/appoint'], resolve),
    meta: {
      title: '人员任命', // 页面标题
      keepAlive: false, // 是否缓存页面
      enterPermission: ['archive:appoint:read'],
      pagePermission: [
        'archive:appoint:update',
        'archive:appoint:read'
      ]
    }
  },

在路由前置守卫中,通过查看store中存放的权限字段 permission 下有无 当前页面的字段,有的话表示已经进入过该页面,权限已经有缓存了,直接走校验权限的函数,没有的话则请求用户的权限 参数是 pagePermission 和 进入页面的path。然后再走校验权限的函数。

 const meta = to.meta
  const path = to.path

  // 存在权限且权限未加载过
  if (meta && meta.enterPermission && !store.state.permission[path]) {
    store.dispatch({
      type: 'getPermission',
      payload: {
        params: meta.pagePermission,
        path,
        success: () => {
          routeNext(to, from, next)
        }
      }
    })
  } else {
    routeNext(to, from, next) // 必须要执行的;进行管道中的下一个钩子;可加参数定义操作
  }

校验权限的函数

通过 页面进入需要的权限enterPermission,同 存放在 store.state.permission[path] 中的用户权限,做比对,确保enterPermission中的每一项都出现在用户的权限列表里,否则表示无权限,跳转到无权限页面。

function routeNext (to, from, next) {
  const meta = to.meta
  const path = to.path
  if (meta.title) {
    setTitle(`${systemKey}-${meta.title}`)
  } else {
    setTitle('好慷在家')
  }
  // 提示权限不足
  if (meta.enterPermission && store.state.permission[path] && !(meta.enterPermission.every(elem => store.state.permission[path].indexOf(elem) > -1))) {
    return next({path: '/notPermission'})
  }
  next()
}

按钮级别的权限控制

自定义组件