笔者实习过程中,主要负责权限模块,也趁机输出一下相关的知识。

ACL

访问控制列表(ACL,即 Access-control list),将一系列的权限与一个系统资源相关联。ACL 专注于个别许可的列表,想象一下你家门口的门禁系统,门禁系统上有一个名单,上面列出了允许进入你家的人的姓名。这个名单就像是一个 ACL,里面记录了具体的人名和他们被授予的进入权限,比如进入、离开、访问特定房间等。只有名单上的人才能够进入你家,其他人则不能。

一般的表结构设计如:ACL 表(对象标识,主体标识,权限标识),对象指需要访问的对象,比如门禁系统中特定的门口,主体代表进入你家的人,权限则标识进入、离开等。

一些变种包括:

  • ACL with superuser

普通用户的权限管理与之前一致,但引入了一个超级用户,不受权限管理控制,拥有所有权限。有了超级用户,排查些问题会比较方便。

  • ACL without users

适用于没有身份验证或用户登录的系统,比如文件共享系统,希望进行访问控制,但又不想为每个用户分配权限,就可以通过定义文件属性(如文件类型、标签、内容等)来管理文件的访问权限,从而更灵活地控制访问。

  • ACL without resources

与 ACL 不同,它不再关心特定的资源,而是专注于对一类资源或者一种操作的权限控制。比如你可以定义一个权限叫写文章,而不用关心具体的哪篇文章。这意味着你可以将 “写文章” 权限授予多个用户,让他们可以写任何文章,而不用每次新建一篇文章都重新设置权限。

RBAC

基于角色的访问控制(RBAC,Role-based access control),主要专注于角色和权限的管理和分配。想象你是一家公司的主管,有员工、经理和管理员等角色。在 RBAC 中,你为每个角色指定了特定的权限集合。例如,员工可以访问公司资源,经理可以管理项目并授予权限,管理员可以管理整个系统。当某人被分配了某个角色,他们就会自动获得与该角色相关的权限,而不需要单独指定。

RBAC 相对于其他访问控制模型,优势在于它的批量操作非常便捷,只需要为这些用户都分配这个角色即可,它们就会获取到该角色拥有的大量权限。而且更改该角色的权限时,无需为这些用户改动。

一般的表结构是一个角色表,一个权限表,一个用户表,一个角色和权限的关联表,一个用户和角色的关联表。当获取一个用户的权限时,根据角色与权限的关联取到权限交集。

变种有:

  1. RBAC with resource roles

通过为资源分配角色,访问控制变得更加细粒度。与其仅仅确定用户是否能够访问资源不同,这种方法允许定义特定操作或操作,特定角色的用户可以对特定资源执行这些操作。

比如一个开放的在线文档平台,有作者、审阅者、访客等角色。对于一篇文档的不同状态,有不同的权限控制:

  • 正在编辑的文档:只有作者可见,只有作者允许编辑。
  • 正在审阅的文档:只有作者和审阅者可见,审阅者无法编辑但可以反馈,作者无法编辑(如果需要编辑,需要等待审阅打回)。
  • 已发布的文档:所有角色都可见,只有作者允许编辑。

这个例子中,不同的用户和文档角色组合导致了不同级别的权限,同时也考虑了文档的不同状态和用途。这种方法有助于确保适当的权限和访问控制,使用户可以在协作环境中高效地工作。

  1. RBAC with domains/tenants

适用于多租户系统,比如在线网课平台,每个学校都是一个租户,每个用户在不同租户中的角色权限都不一样,可以更细粒度的进行管理。这使得平台能够根据不同的领域或租户需求,提供个性化和定制化的权限控制,确保用户可以在不同环境中执行适当的操作。

ABAC

ABAC 是基于属性的访问控制,通过角色属性和资源属性根据策略来控制访问权限。

访问策略通常指:如果你的某个属性为特定属性时,或者达到了某个条件,那么这个资源你就可以进行对应权限的访问。

一般表结构如下:一个实体表,一个资源表,一个实体属性表,一个策略表,一个策略规则表。其中策略表关联了资源表,相当于为该资源设定了访问策略,策略规则表存储了条件、动作等。

假设你在一个虚拟的游戏世界中。在 ABAC 中,访问权限取决于你的属性。每个玩家都有一些属性,比如级别、任务完成情况、特殊技能等。为了获得访问权限,系统会根据你的属性动态地决定是否允许你进入某个区域或执行某项任务。例如,如果你的级别达到了某个要求,你就可以访问一个高级区域。

Deny-override

Deny-override 支持同时使用允许(allow)和拒绝(deny)授权,其中拒绝授权会覆盖允许授权。这种机制用于确定用户是否有权访问资源,即当允许和拒绝授权同时存在时,拒绝授权将优先于允许授权生效。

关键特点在于

  • 允许授权(Allow Authorization):允许授权确定哪些用户或角色可以访问特定资源。这些授权可能基于角色、属性、上下文等条件。
  • 拒绝授权(Deny Authorization):拒绝授权确定哪些用户或角色不允许访问特定资源,即拒绝访问权限。
  • Deny-override 规则:在 Deny-override 机制下,如果一个用户或角色同时有允许和拒绝授权,那么拒绝授权会覆盖允许授权,即拒绝授权优先于允许授权

这种访问权限控制模型笔者没有用过,适用于一些机密文件,可以确保该资源不被不应该访问的用户访问。

Priority

类似防火墙规则,访问策略规可以根据其优先级进行排序,以决定当多个规则适用于同一资源时,哪个规则将被优先应用。这种机制允许管理员灵活地控制访问权限,确保特定规则在发生冲突时能够正确执行。

像 iptables 就是,从上到下多条规则进匹配,然后决定该数据包是 ACCEPT 还是转发等。

RESTful

以 URI 来唯一标识某个资源,然后根据请求方法 GET、PUT、POST 等对资源进行操作。

比较简单的是用户能访问自己的资源,管理员能访问所有的资源。

1
2
3
4
http://localhost:8080/{user_id}/paper

其中{user_id}是用户的唯一标识
根据请求GET,表示获取用户的paper列表,POST表示添加paper,DELETE表示删除paper等。

实践

笔者所在的部门主要维护一个服务于所有业务线的基座平台,该平台上承载着多个 appfy,每个 appfy 都相当于一个业务的闭环,类似于手机上的 app。在 SaaS 业务中,一个 appfy 可能会有一些高级功能或者定制功能,这些功能只提供给付费用户使用。由于业务方向是 B 端的,一个公司在使用过程中需要进行权限管理。

在公司组织架构管理中,常用的访问控制模型是 RBAC,根据用户的角色来分配权限。针对 RBAC 模型,我们将权限维度抽象为权限点,权限点用于控制某个 appfy 的某个功能。通过用户 - 角色 - 权限点的方式来管理公司内的权限分配。

然而,在过去的版本迭代中存在一些问题:

  1. 纯 RBAC 模型无法兼顾高级功能或定制功能的权限分配。权限点没有公司维度,且独属于一个 appfy。如果添加一个权限点用于控制高级功能或定制功能,所有公司在自己的组织架构中都能看到这个权限点。虽然有禁用权限点的功能,但权限点默认都是不禁用的。

  2. 新建立的公司所拥有的 appfy 是通过模板来分配的,但模板分配的维度仅限于 appfy,而非更细分的权限点。

为了解决这些问题,笔者的设计是将权限点进行分类处理,并通过扩展 RBAC 模型来管理公司所拥有的高级、定制权限点。

角色和资源:

  • 角色:公司
  • 资源:带有高级 tag 的权限点

策略规则:

  • 如果用户属于某一个公司,并且公司付费功能包含该功能权限点,则进而根据 RBAC 模型判断用户是否拥有该权限点。

另一方面,为了简化 CSM 对客户公司的权限管理:

  • 如果权限点关联的 appfy 没有为该公司开启,则该权限点将不会允许该公司用户访问。
  • 将部分有关联的高级权限点打包,CSM 进行分配时可以批量分配。

总结

本文介绍了几种权限访问控制模型:ACL、RBAC、ABAC、Deny-override、Priority 和 RESTful,并通过实际案例展示了它们的应用。ACL 强调对象权限关联,RBAC 基于角色分配权限,ABAC 根据属性动态控制,Deny-override 优先拒绝,Priority 排序规则,RESTful 基于 HTTP 方法。通过灵活选择和组合这些模型,可以实现有效的权限管理系统。