后台管理系统的权限自动化实践

date
Apr 17, 2022
slug
boss-auto-auth
status
Published
tags
优化
summary
有关权限自动化的实践在我们项目中已经落地了一段时间,运行的也很顺利了,下面就来分享一下我们项目运行时遇到了什么问题,以及我们是怎么解决的。
type
Post

前言

有关权限自动化的实践在我们项目中已经落地了一段时间,运行的也很顺利了,下面就来分享一下我们项目运行时遇到了什么问题,以及我们是怎么解决的。

项目背景

我们后台管理权限采用的是权限设计模型中的 RBAC(Role-Based Access Control) 也就是基于 角色 的权限控制。
在实际的项目中应用的架构图基本上是这样的:
flowchart LR
    menu1[菜单模块]
    menu2[菜单模块]
    menu11[菜单模块]
    menu21[菜单模块]

    api2[接口权限] --> menu1
    api3[接口权限] --> menu1

    api4[接口权限] --> menu2
    api5[接口权限] --> menu2

    api11[接口权限] --> menu11
    api21[接口权限] --> menu11

    api41[接口权限] --> menu21
    api51[接口权限] --> menu21

    menu1 --> role1
    menu2 --> role1


    role11[角色]
    role1[角色]
    menu11 --> role11
    menu21 --> role11
  user[用户]
  role1 --> user
  role11 --> user

但这样的方案在实际应用中会有那些问题?

  • 菜单模块:实际对应的就是一个路由,路由对应的一个页面
  • 前端模块的显示就是一个 key,根据这个 key,来判断当前用户信息中是否存在该 key,从而决定前端的显示,目前该 key ,是前端开发在开发中自己定义的一个 唯一字符串
 
我们生成环境的角色权限都是由 产品、运营 来配置的,而他们只清楚每个角色应该有哪些菜单模块的权限,不知道菜单模块对接着那些接口权限,而页面中对应那些接口权限只有前端知道,这就造成一个问题,每当有新增菜单模块的需求上线是,前端需要告诉产品,新增了那些菜单对应的 key,以及 key 对应这那些接口权限。
 
而对于产品和运营来讲,他们只关心角色和菜单之间的关系,至于菜单和接口之间的关系对他们来说是负担,而当后台的管理系统用的人和覆盖的国家线越来越多时,沟通成本和理解成本也会越来越高。
flowchart LR
    menu1[菜单模块]
    menu2[菜单模块]
    menu11[菜单模块]
    menu21[菜单模块]

    api2[接口权限] --> menu1
    api3[接口权限] --> menu1

    api4[接口权限] --> menu2
    api5[接口权限] --> menu2

    api11[接口权限] --> menu11
    api21[接口权限] --> menu11

    api41[接口权限] --> menu21
    api51[接口权限] --> menu21



    role11[角色]
    role1[角色]
  subgraph 实际关心
    menu1 --> role1
    menu2 --> role1
    menu11 --> role11
    menu21 --> role11
    user[用户]
    role1 --> user
    role11 --> user
  end

解决问题

那么关于菜单和接口之间的关联关系,可不可以任何人不需要关心呢?
可以。方案是通过 扫描 项目中的每个页面所调用的接口,然后生成一个页面相关的 JSON 文件,然后根据该文件和项目中菜单配置文件生成一个新的文件,该文件的 key 是由菜单的路径标题拼接后hash 生成的唯一 key
 
这里有一个基本实现扫描的脚本的 例子,可以参考一下,执行 node index.js 就会扫描项目并生成一个 menu-config.json 文件。
 
扫描项目生成的 文件权限描述 类似这样:
{
  "src/views/aaa/bbb/test.tsx": {
    "authApiList": [
      {
        "method": "POST",
        "api": "/xxx/ccc/aaa",
        "apiName": "testApi"
      },
      {
        "method": "POST",
        "api": "/xxx/ccc/bbb",
        "apiName": "test1Api"
      }
    ],
    "elementList": [],
    "authElementList": []
  },
// ... 
}
 
项目中 菜单配置
const sideBarList = [
  {
    name: 'test menu',
    type: 'MENU',
    path: '/test',
    children: [
      {
        name: 'test1',
        path: '/aaa/bbb',
        componentPath: '@/views/aaa/bbb',
      },
		]
	}
//...
]
运行时将 文件权限描述 菜单配置 通过 componentPath 匹配后合并为一个新的文件,有了这份 JSON ,就可以实现 自动配置接口自动显示对应模块、更直观的以树形结构 直观的显示权限配置
[
  {
    name: 'test menu',
    type: 'MENU',
		allAuthList: ['21334', '4567']
    path: '/test',
    children: [
      {
        name: 'test1',
        path: '/aaa/bbb',
				key: '21334',
        componentPath: '@/views/aaa/bbb',
				authApiList: [
		      {
		        method: "POST",
		        api: "/xxx/ccc/aaa",
		        apiName: "testApi"
		      },
		      {
		        method: "POST",
		        api: "/xxx/ccc/bbb",
		        apiName: "test1Api"
		      }
		    ]
      },
		]
	}
//...
]
结构图如下:
flowchart LR
  subgraph 菜单模块
    menu1[菜单模块]
    menu2[菜单模块]
    menu11[菜单模块]
    menu21[菜单模块]

    api2[接口权限] --> menu1
    api3[接口权限] --> menu1

    api4[接口权限] --> menu2
    api5[接口权限] --> menu2

    api11[接口权限] --> menu11
    api21[接口权限] --> menu11

    api41[接口权限] --> menu21
    api51[接口权限] --> menu21
  end

    menu1 --> role1
    menu2 --> role1


    role11[角色]
    role1[角色]
    menu11 --> role11
    menu21 --> role11
  subgraph 实际关心
    user[用户]
    role1 --> user
    role11 --> user
  end


  scan[扫描遍历分析]
  project[项目目录]
  buildMenuConfig[生成文件权限描述 JSON]
  menuList[菜单文件配置]
  menuAuthList[菜单文件权限配置]
  pageFolder[页面文件夹]

  project --> menuList
  project --> pageFolder
  pageFolder --> scan
  scan --> buildMenuConfig
  subgraph 关键
    menuList --> menuAuthList
    buildMenuConfig --> menuAuthList
  end
  menuAuthList --> showMenu[模块显示级别展示]
  menuAuthList --> operateRole[简易化操作角色页面]
  menuAuthList --> autoConfig[自动配置接口菜单模块权限]

  autoConfig --> 菜单模块
 

最终效果

改造前
  • 配置繁琐易出错
  • 权限跨国家线迁移困难
  • 前端/测试/产品都需要关心菜单对应那些接口
  • 有认知成本
  • 前端需定义 key 且不统一
改造后
  • 无需配置
  • 一键模块权限更新
  • 所有人无需关心
  • 自动生成 key
简化了新增菜单需求的权限相关流程,上线是只需要点击一个 自动更新的按钮 即可,无需之前繁琐的配置菜单对应那些接口权限。

总结

枯燥无味的后台管理系统也能探索和优化,只要保有一个提效(懒惰)的心。
 

© jianxiaoBai 2021 - 2022