基于 RBAC 权限模型的架构设计

谈到权限控制,实际上在我们的生活中无处不在,例如我们无时无刻都在使用的智能手机,打开手机需要生物指纹或者人脸识别;当你进入公司的时候,你需要工卡在门禁滴一下;又如曾经的你是否有过半夜打开心仪女孩的 QQ 空间,欲一探究竟的时候,却告诉需要添加好友才能访问。这些都是我们日常生活中体现权限的地方,而在软件开发中,权限管理也是无处不在的产品设计功能,尤其是后台管理后台无法对权限管理避而不谈,今天尝试深入了解权限管理设计中最常用的 RBAC 模型。

权限模型

权限 二字从字面上可拆分为 权力+限制,从使用者的角度来说,也就是在限制的范围内正确地行驶权力,而站在设计者的角度来解读,则是通过合理的手段控制使用者能访问到他们能够访问到的资源。

在权限设计领域,最常见的权限模型有以下四种:

  • ACL(Access Control List):访问控制列表 用户 -> 权限
  • RBAC(Role-Based Access Control):基于 角色 的权限控制 用户 -> 角色 -> 权限
  • ABAC(Attribute-Based Access Control):基于 属性 的权限控制,该模型根据特殊的规则分配权限 (用户、资源、对象属性)-> 权限
  • PBAC(Policy-Based Access Control):基于 策略 的权限控制,用户(组)隶属于角色,角色隶属于资源(项目)用户 -> 角色 -> (资源/项目 + 权限)

第一种 ACL 模型,权限能直接赋予用户,例如将查看订单列表(权限)赋予某位运营人员(用户)。但是这种模式的缺点在于,但用户量达到一定量级的时候,那么就需要对每个用户都进行一次授权操作,那么这个工作量就会相当大。

因此就出现了 RBAC 模型,这是软件设计中最常用的权限管理模型,相比于 ACL 模型,RBAC 模型在用户与权限之间多了一个元素「角色」,通过权限关联角色、角色关联用户的方法来间接地赋予用户权限,从而实现用户与权限的解耦。

后两种大概知道就行,因为一般不会用到,详情可自行 Google 了解。

RBAC 模型的演进

在 RBAC 模型的演进发展出四个版本,分别是 RBAC 0~3。

RBAC0 模型

RBAC9 是最基础的权限模型,很多产品基于该模型就已经能满足设计需求。用户和角色之间可以是一对多也可以是多对多关系,而角色和权限之间则多以多对多的关系为主,用户拥有的权限等于他所有的角色持有的权限之和。

应用场景:例如在电商公司中抽象出几种管理业务的角色,诸如销售经理、项目经理、市场经理等等,小陈既担当营销部门的市场经理又担当销售部的销售经理,那么就需要将这两个角色的赋予给他。

RBAC0 模型

RBAC1 模型

RBAC1 模型其实是 RBAC0 的升级版,它对角色这层元素上进行了细分,引入继承的概念,也就是可以继承某个基础角色生成子角色。

RBAC1 模型

应用场景:承接上面的例子,市场经理岗位可能会分为总监级别、经理级别、副经理级别,这时候如果小陈只是一个副经理级别的,那么他所拥有的市场经理的权限肯定就没有总监级别的多。

RBAC1 模型则更好地在角色层面进行细分,更好地映射了企业组织架构中的职能的权限,根据实际的管理权限对相似职能的角色进行删减以达到级别分明的效果。

RBAC2 模型

在 RBAC2 中对角色层面增加了更多的限制:

  • 静态职责分离 SSD
    • 角色互斥:相同用户不能同时拥有互斥关系的角色,例如会计和出纳两个角色就是互斥的
    • 基数约束:角色被分配到的用户有数量上限,例如公司中只有一个 CEO 职位,那么这个角色的数量就是有限的
    • 先决条件角色:要拥有更高级别的角色权限,需要先获取到相对来说低级别的一些权限,例如副经理要想获取到总监级别权限,那么他需要先获取到经理级别的权限
  • 动态职责分离 DSD
    • 动态的限制用户及其拥有的角色,例如一个用户可以同时拥有两个角色,但是运行时只能激活一个角色

RBAC2 模型

RBAC3 模型

RBAC3 模型就是 RBAC1 + RBAC2 两个模型的合集,所以 RBAC3 既有 RBAC1 的角色等级划分,也有 RBAC2 的角色限制。这种模型只有在系统比较复杂的时候才派得上用场,不然设计得过度复杂,对开发和后期维护也不是好事情。

RBAC 模型的优缺点:

优点

  1. 简化了用户和权限的关系,权限只要一次赋予角色就能重复使用
  2. 对后续的维护更加友好,用户和权限之间存在更多的斡旋空间,便于基于角色进行权限扩展

缺点

  1. RBAC 模型并未提供控制操作顺序的机制,会对有严格操作顺序的系统造成困难

RBAC 架构设计

前面我们提到 RBAC 涉及三个层面,就是用户、角色和权限。

用户我们可以理解为独立的个体,例如张三、李四、王五。而角色的定义是很广泛的,如果我们从职位划分有销售经理、市场经理、项目经理等等,按部门划分的话可以是销售部、市场部、项目部,所以说角色应该按照系统的业务需求来划分。而事实上,在我们的架构设计中需要对用户和角色的关系进行描述,比如其内容应该是张三是销售经理、李四是市场经理、王五是项目经理。

还有就是权限层面,权限层面可以划分为查看客户列表、添加客户、删除客户等等。权限和角色是绑定起来的,所以角色和权限的描述可能是这样的:销售经理可以查看客户、添加客户、删除客户;销售仅可以查看客户。

RBAC 架构设计

在实际的业务开发中,可以对 RBAC 模型做相关的扩展,例如在员工人数众多的情况下,反复地对某个员工进行权限授予是个繁琐的行为,我们可以增加 用户组 的概念,直接给用户组分配角色,再把用户加入用户组,这样用户除了自身的权限外,还共享了用户组的所有权限。

数据库与功能模块设计

在架构设计的章节中我们提到了除用户、角色和权限外,他们相互联系的关系共五个层面,映射到数据库的设计对应的就是五张表。

  • user(用户):每个用户都有唯一的 UID 识别,并被授予不同的角色
  • role(角色):不同角色具有不同权限
  • permission(权限):访问权限
  • 用户-角色映射:用户和角色之间的映射关系
  • 角色-权限映射:角色和权限之间的映射

数据库设计

功能模块

前端权限控制思路

前端权限从本质上来说即根据权限表对视图层的展示以及对请求接口的访问进行限制。

下面我们谈谈前端界面对于权限控制的粒度大小,以传统的后台系统为例,有以页面为维度作为权限控制粒度的,拥有权限的人员方可访问对应的页面;有以操作作为权限控制的,对应的前端界面中的页面元素需要隐藏或提示;也存在用户通过浏览器的开发者工具修改 DOM 元素以绕过权限直接操作的,这时候就需要对接口请求做拦截。

  • 页面权限(菜单权限):进入页面的权限
  • 操作权限:增删改查的权限
  • 数据权限:发送接口到服务端的权限

Ant Design Pro

在传统的后台系统中会在登录请求中,得到用户所拥有的权限数据,这部分是需要后端的技术支持的。前端根据权限数据展示对应的菜单,点击菜单,才能查看相关的界面。

界面的控制:如果用户没有登录,手动在地址栏上跳转到管理界面地址,则需要跳转到登录界面。如果用户已经登录,但是手动输入非权限范围内的界面地址,则需要重定向到预设的 404 界面。

如果用户通过非常规操作,比如通过浏览器将某些禁用按钮变成启用状态,此时发送的请求,也应该被前端拦截。

在 React 中,可以通过把权限数据在根节点通过 Context API 向下传递,通过高阶组件对权限控制的菜单、元素进行外层包裹,其次对于数据请求拦截可以在发送 HTTP 请求前做校验。

可以参考 Ant Design Pro 的权限设计。


参考资料:

0%