作者:管理员  历史版本:1  更新时间:2024-11-20 15:41

权限控制

权限控制是中后台系统中常见的需求之一,你可以利用我们提供的 路由权限指令权限,实现一些基本的权限控制功能,IBPS平台中也包含了几个简单示例以提供参考

一、路由和默认权限控制

IBPS平台 提供了两套权限实现方案:

  1. 方案一:前端固定路由表和权限配置,由后端提供用户权限标识,来识别是否拥有该路由权限。
  2. 方案二:后端提供权限和路由信息结构接口,动态生成权限和菜单。

1.1、方案一:前端固定路由表和权限配置方案

步骤如下:

  1. 判断是否有Token 如果没有则跳转到登录页面

  2. 如果有Token获取用户信息和拥有权限store.dispatch('ibps/user/load')

  3. 用户信息获取成功后, 调用菜单初始数据store.dispatch('ibps/menu/init')根据获取到的用户信息构建出一个已经过滤好权限的路由结构(@/router/utils.js)

  4. 将构建的路由结构信息利用Vue-Router 提供的动态增加路由方法 router.addRoute 加入到路由表中(说明:vue-router 3.5.0+版本采用router.addRoute替换router.addRoutes 【下同】)

  5. 加入路由表后将页面跳转到用户原始要访问的页面,如果没有 redirect 则进入默认页面 (/dashboard)
    这里可以看出把 登录获取用户信息分成了两个接口,主要目的在于当用户刷新页面时,可以根据登录时获取到的身份令牌(cookie/token)等,去获取用户信息,从而避免刷新需要调用登录接口

IBPS平台 实现的路由权限的控制代码都在 @/router/index.js 中,如果想修改逻辑,直接在适当的判断逻辑中next() 释放钩子即可。
两套权限实现 均使用@/router/index.js(路由守卫)来进行控制。

1.2、方案二:动态权限(平台默认方案)

    但其实很多公司的业务逻辑可能并不是上面描述的简单实现方案,比如正常业务逻辑下 每个页面的信息都是动态从后端配置的,并不是像 默认的路由表那样写死在预设的。你可以在后台通过一个 tree 或者其它展现形式给每一个页面动态配置权限,之后将这份路由表存储到后端。

权限/菜单 eg:

角色 eg:

由 角色关联 到多个 权限(菜单) 。 角色 1 对多权限,用户 1 对多角色 (或 用户1 对 1 角色);

当用户登录后得到 用户信息,前端根据 用户信息 去向后端请求可访问的路由表,从而动态生成可访问页面,之后就是 router.addRoutes 动态挂载到 router 上,你会发现原来是相同的,万变不离其宗。

eg:// 后端返回的 JSON 动态路由结构

// 生成路由代码 @/router/utils.js 以下截取部分

/**
 * 构建子路由
 * @param {*} menus
 */
function generateSubRoutes(menus) {
  const pool = []
  const push = function(menus, namePrefix = []) {
    menus.forEach(menu => {
      const router = {
        id: menu[idKey],
        parentId: menu[parentIdKey],
        path: [...namePrefix, menu[nameKey]].join('/'),
        name: [...namePrefix, menu[nameKey]].join('-'),
        alias: defaultRouterAlias + menu[nameKey],
        component: getComputedUrl(menu[urlKey]),
        // hidden: menu[displayInMenuKey] === 'N',
        meta: {
          title: menu[labelKey],
          icon: menu[iconKey] || 'file-o',
          name: menu[nameKey],
          defaultUrl: menu[urlKey],
          ...meta
        }
      }

      if (menu[childrenKey] && menu[childrenKey].length > 0) {
        if (menu[urlKey]) {
          pool.push({
            ...router
          })
        }
        push(menu[childrenKey], [...namePrefix, menu[nameKey]])
      } else {
        pool.push({
          ...router
        })
      }
    })
  }
  push(menus)
  return pool
}

二、指令权限

IBPS平台 封装了一个非常方便实现按钮级别权限的自定义指令。v-permission

使用

<!-- eg: 当前页面为 dashboard -->

<template>
    <!-- 校验是否有 dashboard 权限下的 add 操作权限 -->
    <a-button v-permission="add" >添加用户</a-button>

    <!-- 校验是否有 dashboard 权限下的 del 操作权限 -->
    <a-button v-permission="del">删除用户</a-button>

    <!-- 校验是否有 dashboard 权限下的 edit 操作权限 -->
    <a v-permission="edit" @click="edit(record)">修改</a>
</template>

需要注意的是,指令权限默认从 store 中获取当前已经登陆的用户的角色和权限信息进行比对,所以也要对指令权限的获取和校验 Action 权限部分进行自定义。

其中在数据模版中 权限key

ibps_data_template_tpl_+模板key+_+按钮key

在某些情况下,不适合使用 v-permission,例如 Tab 组件,只能通过手动设置v-if 来实现。或者disabled 属性进行禁用

这时候,IBPS平台为其提供了原始v-if 级别的权限判断。

以上代码的 if 判断会检查,当前登录用户是否存在 dashboard 下的 add / del / edit 权限

实现思路:
在 Vue 初始化时,@/plugins/permission.js 作为插件注册到 Vue 原型链上,在 Vue 实例中就可以用 this.$auth()方法进行权限判断。 当然这里也要对权限的获取和校验 Action 权限部分进行自定义。