相关文章

系统设计之基于资源角色的权限管理

 |   

权限管理是所有后台系统的一个重要组成部分,其目的是控制用户(User)对资源(Resource)的操作(Action),避免因为权限控制缺失或操作不当引发风险,比如操作失误,隐私数据泄露等问题。 迄今为止最为普及的权限设计模型是基于角色的访问控制模型(Role-Based Access Control)。它主要是将用户和用户组捆绑在一起叫主体,资源和操作捆绑在一起叫权限,中间用角色做桥梁关联二者。 但近年来随着对数据管控的精细化,资源和操作的捆绑成为了其掣肘。所以资源也需要像用户那样拥有资源组的概念,这样就变成了用户/用户组对资源/资源组有操作权限,这就是基于资源角色的访问控制模型。 本文将详细描述基于角色的访问控制模型到基于资源角色的访问控制模型的进化过程,并使用强大、高效的开源访问控制框架 Casbin 来设计一个基于资源角色的访问控制系统。

背景介绍

最近在做产品权限模块的开发,大致的需求如下:

  1. 系统要有角色的概念,不同的角色有不同的功能权限,并能够支持用户自己适配
  2. 系统能支持公司组织的管理,并能够支持多个层级(不超过10个)
  3. 系统能够支持对单个文件资源的控制,也能支持对多个文件资源的控制。

对于需求 1 和 2,基于角色的访问控制模型 RBAC 就能够很好的支持,而对于需求 3,我们对其做了充分的讨论,发现了 RBAC 的不足,并对其做了改进升级。

RBAC 介绍

基于角色的访问控制模型 RBAC 在 20 世纪 90 年代期间被大量的专家学者和研究单位进行了深入的研究,先后提出了很多 RBAC 模型。这些模型主要为了解决这样一个问题:判断用户对资源的操作是否为真。它需要支持三个公认的安全原则:

  • 最小特权原则:模型分配给用户的权限不能超过其完成任务的需要即可(通过限制分配给角色权限的多少和大小)
  • 责任分离原则:同一用户只能分配到一组互斥角色集合中至多一个角色(通过调用相互独立互斥的角色来共同完成敏感的任务)
  • 数据抽象原则:用户对资源的操作可以抽象,不限于操作系统提供的读,写,执行权限(操作支持适配)

1996 年以美国 George Mason 大学信息安全技术实验室(LIST)提出的 RBAC96 模型最具有系统性,得到了普遍的公认。它是一个模型族,包括了 RBAC0 ~ RBAC3 四个概念模型。

RBAC0

RBAC0 定义了完全支持 RBAC 概念的任何系统的最低需求:用户,角色,权限。其中用户和角色是多对多关系,角色和权限也是多对多关系。其 E-R 如下:

rbac0-er

  • 用户 是发起操作的主体,比如测试人员,普通人员,管理人员
  • 角色 是连接用户和权限的桥梁。它既关联了多个权限,也关联了多个用户。设计角色的原因是因为很多人的权限是一样的。如果直接关联,给 100 个人分配 10 个权限要做 1000 次关联操作,而使用角色则需要 10(权限-角色) + 100(用户-角色) 次关联操作。
  • 权限 是资源和操作组合,它的总数是资源数 * 操作数。比如文件 f 可读,文件 f 可写,文件 f 可删。这里的资源包括页面菜单资源,接口访问资源和数据资源。
    • 页面菜单资源 指系统的导航菜单,包括多级菜单
    • 接口访问资源 指页面的功能按钮,包括增,删,改,查等操作,其对应着后台接口的访问。(一般系统会要求“可见即可操作”)
    • 数据资源 指用户在同一个页面能看到的数据是不同的,比如采购部只能看采购部上传的文件,其它部门看各自部门的数据。(一般会把数据资源和具体的组织架构关联起来)

RBAC1

RBAC1 在 RBAC0 基础上增加了角色分级的概念, 也就是一个角色可以从另一个角色继承权限。不过这种权限继承是一个绝对偏序的关系,也就是树结构继承,不能出现闭环。这种设计可以给用户分组和分层,在一定程度上简化了权限管理工作。其 E-R 如下:

rbac1-er

相较于 RBAC0, 角色表新增了 父节点id 这个属性来实现角色的权限继承问题。

RBAC2

RBAC2 在 RBAC0 基础上增加了角色的约束控制:责任分离,它规定了权限被赋予角色时,角色被赋予用户时,以及当用户在某一个时刻激活一个角色时所应遵循的强制性规则。责任分离包括静态责任分离和动态责任分离。主要包括以下约束:

  • 互斥角色 同一个用户只能分配到一组互斥角色集合中最多一个角色,支持责任分离原则。互斥角色是指各自权限相互制约的两个角色。比如财务审计中会计员和审核员的两个角色,这两个角色是互斥的,同一个用户不能同时拥有者两个角色。
  • 基数约束 一个角色被分配的用户数量受限,一个用户所用的角色数目受限,同样一个角色对应的访问权限数据也应受限,以控制高级权限在系统中的分配。
  • 先决条件角色 用户想要获得上级角色必须先获得其下一级的角色。

相较于 RBAC0, RBAC2 对角色的创建以及用户和角色,角色和权限的关联做了限制。这块的变动主要是为了规范角色的使用,毕竟实现权限控制可以不用角色:直接让用户和权限关联。使用角色的目的就是为了简化权限管理工作,但不合理的使用可能使权限管理变得复杂,所以才有了角色的约束控制。这块的规则对于 E-R 图没有任何变动,主要受产品的业务逻辑影响较大。

RBAC3

RBAC3 是在 RBAC0 的基础上,将 RBAC1 和 RBAC2 进行整合而形成的最全面的权限管理模型。下图是 RBAC96 模型的示例图。该图展示了 RBAC0 - RBAC3 的模型范畴。

rbac3

RBAC扩展-用户组

背景

在很多的管理系统或者平台有应用中,我们都会发现在系统中有用户组这样用户集合的概念,比如组织架构,职位。用户组的出现主要有两个原因:

  • 管理方便,减少 admin 的工作量
  • 用户集合贴合公司实际情况

第二点比较好理解,毕竟任何公司都有不同的岗位以及它的组织架构。第一点可以这样理解:当系统中用户数目和角色数目较多时,很容易出现一部分人拥有相同的权限特性,比如研发部的所有员工,各个分公司的开发人员。如果直接给用户分配角色,管理员的工作量就会很大(用户分配多个角色),此时将相同特性的用户规整到某个用户组,那么管理员直接给用户组分配角色,在用户组的中每个用户都拥有该角色。这样用户加入或退出某用户组就实现了用户的角色变更,无需 admin 管理角色。

落地

用户组是一个比较抽象的概念,它表示用户的集合,它和权限的关联还是需要通过角色来实现的。根据是否有上下级关系可以分为两类:

  • 具有上下级关系的用户组: 最典型的例子就是组织架构和职位。
  • 普通用户组: 也就是没有上下级关系。比较典型的就是公司里的虚拟小组和工会小组,它们的特性就是跨部门。虚拟小组是指针对某个项目临时抽调不同部门的同事构成虚拟的项目小组。工会小组是指公司中通过兴趣爱好构建的活动小组,比如篮球小组,羽毛球小组等。

因为组织架构比较常见,所以这里以组织架构为例来构建它的 E-R 图。

rbac_usergroup

系统中如果同时存在组织架构和职位这样的设计,可以将二者放在同一张表中,以用户组类型字段来进行区分。当然如果两个实体的属性差异较大时可以分开来建表。此外用户属组关系表和用户组角色关系表是否存在(多对多关系需要,1对多关系可以集成到多的属性中)看具体的业务需求。推荐使用多对多关系,这样系统的可扩展性比较好。

难点解释

  • 角色和用户组的异同

用户组是用户的集合, 角色是用户/用户组与权限的关联媒介,这是二者最大的差别。在同一个系统中,如果用户组的权限和成员仅可以被 admin 修改的话,用户组的机制是非常接近角色的概念。此外角色也可以在用户组的基础上实现,这有利于保持系统中的控制关系,此时角色和用户组是一对一的关系。

  • 数据权限

博文中提到组织架构的另外一个作用是控制数据权限,把角色关联到组织,那么该用户就只能看到该组织下的数据权限。的确,通过角色将组织和权限关联起来,同一个组织中的用户可以共享角色,也就意味着可以共享权限(资源+操作),也就意味着可以共享数据资源。这种数据权限的控制是该方案天然自带的,也就是不管你要不要这种特性,它必然存在。而且如果你想做其它的数据控制,比如标注员对不同用户组上传的标注数据有标注的权限,此时只能通过创建新的角色来解决。

RBAC扩展-资源组?

RBAC模型能支持资源组的概念么,理论上是不行的。

需求背景

工作中碰到不少项目,客户对数据资产的管理要求很严格,特别是当下大数据时代,数据湖的概念在业界弥漫。客户需要的产品能够支持对数据资产的严格把控。这些数据只有个别角色可见,那些数据只有某个特定角色可以修改等等。这里需要注意以下几点:

  • 数据资源是用户产生的,是后天的。与之相反的是页面菜单和接口访问,它们是先天的,系统出厂就已经定义好的。
  • 数据资源理论上是没有上限的。因为是用户上传的,只要硬件支持,理论上数据资源的数目是不受限的。页面菜单,接口访问都是有限的。
  • 数据资源需要支持资源的分页展示以及基本的字段筛选

理论不可行

从上面的注意点,我们发现 RBAC 模型天然对数据资源的管理比较弱,因为它只能支持最小粒度的资源,无法支持资源组的概念。为什么?因为 RBAC 模型最基本的前提假设是权限是资源和操作的乘积。对于页面菜单和接口访问,因为产品出厂即可初始化,而且数目有限,所以和操作的数目乘积也是屈指可数。但是对于数据资源而言,那就很夸张了。而且每增加一个数据资源就需要增加操作个数的权限记录了,除了创建者对该数据资源进行分配外都需要 admin 来进行权限分配。

基于资源角色的权限管理

RBAC 引入资源组

RBAC 模型最大的问题是资源和操作的耦合性较高,导致资源组的概念无法加入其中。要想引入资源组,需要重新定义权限和角色。 这里定义权限是个三元组<用户/用户组,资源/资源组,操作>,表示用户或用户组对资源或资源组的操作。角色属于用户组的一种,它和系统先天资源(页面菜单和接口访问)相对应,而用户组(组织架构和职位)和系统后天资源(数据资源)相对应。

TIPS: 在该模型中的角色不再是用户和资源加操作的乘积,而是用户组的一种,和组织架构,职位是同等地位的,区别在于角色对应系统的先天资源/功能资源,组织架构这些对应系统的后天资源/数据资源。这里角色不再是之前的概念是因为权限三元组已经完全取代了原来旧角色:集合用户,资源,操作。

这里给出一个实际的应用场景以及对应的 E-R 图。

rrbac

上图的实体表说明:

  • 用户表 用户信息
  • 角色表 根据系统的功能划分的用户集合,比如标注员,审核员等。支持层级
  • 用户组表 根据数据的权限划分的用户集合,比如组织架构,职位等。这个和角色表有点类似,毕竟都是用户的集合,只不过划分的维度不一样。支持层级
  • 按钮表 系统的所有可点的按钮或链接,其包括导航栏,也包括具体按钮,当然有的按钮还对应具体的路由请求。
  • 功能组表 是按钮的集合,比如对文件的操作会包含增加,删除,编辑,列表查看,详情查看等多个按钮。支持层级
  • 文件表 用户上传的文件,是一种数据资源
  • 加工表 用户通过加工文件得到的新的数据资源,比如抽取文件构建图谱等。
  • 数据组表 数据资源组表,通过数据组类型进行数据资源区分。支持层级

关系表说明:

  • 用户角色表 用户和角色的关系表
  • 用户属组权限表 用户和用户组的关系表
  • 功能按钮权限表 功能组表和按钮表的关系表
  • 文件组文件权限表 文件组和文件的关系表,该表示文件能够列表展示的关键
  • 文件组加工权限表 文件组和加工的关系表,该表示加工数据能够列表展示的关键
  • 角色功能权限表 角色表和功能组表的关系表,通过一定的逻辑可以替代角色按钮权限表,用户按钮权限表,用户功能权限表。包含操作属性
  • 用户组数据组权限表 用户组合数据组的关系表,通过一定的逻辑可以替代用户数据组权限表,用户文件权限表,用户组文件权限表,用户加工权限表,用户组加工权限表。包含操作属性

Casbin 框架

通过上面的 E-R 图,虽然实现了相应的功能,但是需要创建的关系表太多。有没有简单粗暴的解决方案呢?答案就是使用 Casbin。它是一个强大的,高效的开源访问控制框架,其权限管理机制支持多种访问控制模型。

为什么 Casbin 能够实现上面的需求,有以下几点:

  • 支持自定义请求的个数,默认请求格式为 {subject, object, action}。这点和我们权限的定义<用户/用户组,资源/资源组,操作>不谋而合。
  • 具有访问控制模型 model 和策略 policy 两个核心概念。从 RBAC3 中加入用户组,再试图加入数据组,可见 E-R图的变动是很夸张的,而 Casbin 天然支持多 model。
  • 支持 RBAC 中多层角色继承,不止主题可以有角色,资源也可以有角色。这里的角色就是组的概念,和上面的设计类似,不过上面做了更细的划分。
  • 不支持用户列表和角色列表的管理,只存储用户和角色的映射关系。Casbin 的权限表是用来取代关系表的。如果用户和角色不是很多(万级别以上)可以直接搜数据库, 如果记录数很多可以像文件组文件权限表那样增加关系表。

下图给出了上面的样例 E-R 图如何转变成使用 Casbin 来构建表结构,并能够支持上述需求的。这里需要注意的是文件组文件关系表和加工组加工关系表是保留的。保留的原因是文件表和加工表的记录数很大(万级别以上),如果单纯的使用g2规则的话, casbin规则表会增加很多条记录(万级别以上)。

rrbac_casbin

对比 E-R 图的前后变化,发现基于 Casbin 实现的资源角色管理模型将很多用户和资源的关系表转换成 g 规则和 g2 规则,将很多权限表变成 p 规则。从而大大缩减表结构。此外因为 casbin 规则表都会加载进内存,所以它判定用户对资源有没有相应的操作权限很快。而该表的记录数在合理的设计下基本会成线性增长。而每条记录的长度基本可以保持一定长度不变(不存储详细信息,只标识唯一id)。

参考文献

  1. RBAC用户、角色、权限、组设计方案
  2. 可能是史上最全的权限系统设计
  3. rbac96模型ppt
  4. casbin官网
技术茶话会
< 前一篇 后一篇 >