基于「角色」的权限模块设计

权限管理基础版可优化点

  1. 新功能对应的接口,添加到对应权限集合后,无法直接生效。需要人工移除角色中的权限集合,再重新添加。操作流程复杂,会影响线上用户。
  2. 不支持基于前端路由的权限管控。
  3. 不支持一个用户多个角色。

映射关系

二期支持一个用户多个角色,用户、角色、权限集合、接口的关系调整如下:

007S8ZIlgy1gjtcb4nsbhj311g0oyabl.jpg

映射信息存储

后端保存:

  • 用户 <=> 角色列表
  • 角色 <=> 权限集合列表
  • 角色 <=> 路由列表(路由是可以是字符串或者 Regexp)

前端保存:

  • 权限集合 <=> 接口列表

中间层:不保存信息

为什么前端保存”权限集合 <=> 接口列表”映射?

  1. 从操作角度:功能可能涉及多个接口,人工为用户添加接口权限容易遗漏,不方便定位问题。
  2. 从开发成本:新功能开发时,前端直接在配置文件为权限集合添加接口名即可。
  3. 从安全性:只有内部用户。

功能和流程介绍

权限集合相关

支持以下功能:

  • 读取权限集合

页面可以展示的权限集合,受前端文件管控。如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
const PERMISSION_SETS = [
{
name: "套餐调整",
key: "taocan",
apis: [
"qbase.one",
"qbase.two",
// ...
],
},
// ...
];

角色相关

支持以下功能:

  • 添加角色信息
  • 修改角色信息
  • 删除角色信息
  • 为用户添加角色
  • 为用户修改角色
  • 为用户移除角色

角色信息包括以下内容:

1
2
3
4
name<string>: 角色名
description<string>: 角色描述
permissions<string[]>: 权限名列表
routes<Array<string | Regexp>>: 可访问路由列表

添加和修改角色信息时,会自动读取权限集合信息(存在前端配置),操作者根据需要为角色添加对应的权限集合。

一个用户可以添加多个角色。

基于路由的权限校验

007S8ZIlgy1gjtcc4rirrj315g0mngp7.jpg

注意:中间层传给后端用户名和 url,后端在校验 url 时,应该进行正则匹配。

例如:中间层传入 yuanxindong (用户名)和 /role/ (路由)。后端根据用户名,查找到对应多个角色,再查询各个角色的路由列表并进行整合,最后正则匹配路由,返回中间层匹配结果 true / false 。

基于接口的权限校验

007S8ZIlgy1gjtcbx3vijj315g0kzjvd.jpg

注:页面校验成功后,用户才能调用此页面的功能,顺序为 页面校验 => 接口校验

补充问题

不同的权限集合下不能有相同的接口

场景:如果 A 权限和 B 权限都有 api1,那么进行接口校验的时候,前端会查出 api1 对应的 2 个权限集合名,需要发起两次查询;或者是,权限检验接口支持对用户名和权限集合名列表的入参,增加了复杂度。

解决方法(已确定):

  • 前端添加启动时会自动检查不同权限不能有相同接口,否则构建打包失败
  • 产品明确某个权限集合的职能范围,一个接口只属于某个权限集合
  • 更灵活的配置做法:每个角色可以有多个权限。

基于路由的权限校验性能问题与优化方案

场景:

  • 前端频繁切换,接口调用次数过多
  • 后端需要联表查询并进行正则匹配,性能损耗

解决方法:

  • 「基于路由权限校验」部分中,后台返回当前用户支持的路由列表(性能:后端不需要对大量规则正则匹配
  • 中间层原路透传路由列表给前端
  • 前端将路由列表存储到 Store 中
  • 同一个 tab 下的路由切换,直接从前端 Store 中读取校验即可(传输:节省网络 IO

优化后,基于接口的权限集合校验设计图如下:

007S8ZIlgy1gjtcbidykfj315g0iywi2.jpg