今天咱们一起聊聊权限系统。
以大家熟知的电商场景举例:
- 用户可以分为普通用户、VIP用户:我们需要控制不同角色用户的访问范围。比如,京东的PLUS会员,可以进入会员专区,而且能够使用礼金领取优惠券,但是普通会员没有这项功能;
- 用户还可以范围顾客、商家:顾客可以从APP下单,可以查看自己所有的订单,这些订单属于不同的商家;商家可以从后台看到自己店铺的所有订单,这些订单分属不同的顾客。
对于一个闭环的系统来说,无论是ToC还是ToB,权限系统都是基础组件,用于保障用户在权限范围内操作有权限的数据。
如何控制权限
既然要控制权限,那我首先需要清楚需要控制的因素有哪些?
第一是控制维度,用户可以做什么(Operation),在哪些对象(Object)操作:
- 比如:对某个数据的查询、编辑、删除。我们可以将之称为功能权限。功能权限又可以细化为,看到菜单、打开页面、页面中有哪些按钮、可以访问哪些请求等。
- 比如:A可以管理甲乙丙三个店铺;B可以管理丁一个店铺。我们可以称之为数据权限。数据权限可以细化为:单点、级联、递归等。
控制维度
第二是控制粒度,我们的权限可以控制到一组人员,还是控制到一类人员:
- 按组区分:按照人员的角色进行划分,比如,A、B、C是同一个部门,具备的权限都是一样的,相同的功能权限、数据权限;
- 按类区分:按照用户的特征进行划分,比如,A、B、C是同一个部门,数据权限相同。但是A是正式员工,可以有删除权限;B是正式员工,但是上个月绩效太低,删除权限被收回;C是实习生,只能有查询权限,而且只能看到一个店铺的数据。
两种方式正好对应的业界常用的两种权限模型:基于角色的访问控制(Role-based access control,简称 RBAC)、基于属性的访问控制(Attribute-Based Access Control,简称 ABAC)。
什么是 RBAC
顾名思义,基于角色的访问控制,就是给用户定义角色,通过角色来控制权限。目前来说,基于角色权限控制模型是应用较广的一个。
在RBAC中,包含用户(User)、角色(Role)、权限(Permission),权限又分为对象(Object)、操作(Operation),总共五个基本元素。考虑到多种系统集合或者不同场景,还引入了会话(Session)。
用户与角色之间是多对多,一个用户有多个角色,比如既可以员工也可以是小组长;一个角色可以有多个用户,比如公司所有人都是员工。
一个角色可以多种权限,这个很好理解。每个角色可以有查看、编辑等多种权限。
权限分为操作权限和对象权限,有的地方也称为功能权限和数据权限。一个对应着可以执行的动作,一个对应着动作的数据范围。
在这个模型中,还会细分为4个等级:
RBAC0
RBAC0
RBAC0包含了RBAC的所有元素,是RBAC的基本模型。几个元素之间,就是简单的多对多的关系。我们在市面上见到的大多数RBAC模型都是处于这个阶段。
用户根据会话选择对应的角色,然后根据角色配置的操作权限,可以在系统中看到菜单、页面、按钮等,根据角色对应的数据权限,可以从对应的页面看到对应的数据。
RBAC1
RBAC1
RBAC1是基于RBAC0,引入了角色继承能力。比如有员工角色,可以浏览内部系统的公开信息,然后有老板角色,可以继承员工角色,也就具备浏览内部系统的公开信息的能力。从用户体验上没有差别,但是从事物认知上,更加符合我们的习惯。
RBAC2
RBAC2
RBAC2也是基于RBAC0,与RBAC1不同,RBAC2是增加了对角色的控制:
- 静态职责分离(Static Separation of Duty,简称SSD):
互斥角色:用户只能分配一组互斥角色集合中的一种,比如会计和出纳;
基数约束:一个角色可以被分配给有限的用户,一个用户可拥有有限的角色,一个角色对应有限的权限;
先决条件角色:想获得较高的权限,要首先拥有低一级的权限。
- 动态职责分离(Dynamic Separation of Duty,简称DSD)
运行时互斥:一个用户可以具备两个角色,但是这两个角色不能同时激活。
RBAC3
RBAC3
RBAC1和RBAC2具备两种不同的思想,我们都想要,于是有了RBAC3。
实践中的使用
一般来说,上面几种模型可以覆盖我们大多数的场景。有时候,我们还可以针对自己系统特点,还可以做一些扩展。
对于用户比较多的系统,相同角色的用户可能比较多,比如有100个用户都有角色1和角色2,某一天系统升级,增加了新功能,创建了角色3,于是需要给这100个人都增加角色3,操作起来不太方便。我们可以增加用户组的概念,拥有相同角色的用户添加到一个用户组中,用户组与角色绑定,当需要给一部分用户增加或减少角色的时候,只需要修改用户组与角色的关系即可。
用户组
权限分为操作和对象,一般在实践中中,也会将角色分为操作角色和对象角色,两者彼此分离。
角色
还有一种场景是,针对某些对象,可以有查看和编辑的权限,针对另外的对象,只有查看权限。这个时候,我们需要建立三者关系,角色、操作权限、数据权限。用户具备角色一,角色一可以操作对象一、对象二,对对象一可以查看和编辑,对对象二可以查看。这种场景是更加细粒度的控制。只有在管控非常严格的系统中才会看到,比如,财务系统。
角色/操作/对象
什么是 ABAC
上面提到的最后一种场景中,我们能够看到用户在对象权限和操作权限上的灵活配置。本节我们介绍一种更加灵活的模型:基于属性的访问控制(Attribute-Based Access Control,简称 ABAC),它的原理是通过属性组合动态判断一个操作是否可以被允许。
考虑ABAC的模型时,我们需要一个更加复杂的场景:OA系统中的文档系统(下面例子灵感来源于Authing官网)。
- 授权员工张三有《xxx公告》的编辑权限;
- 当《xxx公告》的所属部门跟李四的部门相同时,李四可以访问这个文档;
- 当王五是《xxx公告》的拥有者并且《xxx公告》的状态是草稿时,王五可以编辑这个文档;
- 早上九点前禁止 A 部门的人访问《xxx公告》;
- 在除了上海以外的地方禁止以管理员身份访问 A 系统。
从上面这个例子中,我们可以看到ABAC模型与RBAC模型的区别:RBAC是静态的,用户具备的权限只与关联角色相关,不随自身特征变化而改变;ABAC是动态的,时移世易,随着用户特征值的变化,权限也随之变化。如果将角色看做一种特征值,那RBAC就是一维的ABAC。
ABAC
在 ABAC 模型中,一个操作是否被允许是基于对象、资源、操作和环境信息共同动态计算决定的:
- 对象是当前请求访问资源的用户,用户的属性包括ID、员工性质(正式、实习、外包等)、员工类型(普通、销售、一线等)、岗位角色、所在部门、办公地点、组织成员身份等;
- 资源是当前用户要访问的资产或对象,例如文件、数据、服务器、API等;
- 操作是用户试图对资源进行的操作,常见的操作包括查询、编辑(新增、修改)、复制、删除、导出等;
- 环境是每个访问请求的上下文,环境属性包含访问的时间、位置,对象的设备,通信协议和加密强度等。
在 ABAC模型 的决策语句的执行过程中,决策引擎会根据定义好的决策语句,结合对象、资源、操作、环境等因素动态计算出决策结果。每当发生访问请求时,ABAC模型决策系统都会分析属性值是否与已建立的策略匹配。如果有匹配的策略,访问请求就会被通过。
DAC与MAC
为了本文的完整,这里在介绍一下常见但是不常用的两个模型:
- 自主访问控制(Discretionary Access Control,简称DAC):被操作对象,根据访问控制规则(权限控制列表(ACL: Access Control List)或者权限控制矩阵(ACL: Access Control Matrix)),来判断操作主体可对操作对象做哪些操作,比如只读或者是可写的权限。而自主的含义,则是拥有某种权限的用户,可以把权限赋予其他用户。
- 强制访问控制(MAC: Mandatory Access Control):被操作对象及用户两方均有各自的权限标识,用户能否对对象进行操作,取决于双方的权限标识的关系,这个限制判断通常是由系统硬性限制的。这种模型多用于等级制度明显,信息访问安全性要求高的场景,比如军事。
文末总结
本文一共介绍了四种常见权限模型:基于角色的访问控制(Role-based access control,简称 RBAC)、基于属性的访问控制(Attribute-Based Access Control,简称 ABAC)、自主访问控制(Discretionary Access Control,简称DAC)、强制访问控制(MAC: Mandatory Access Control)。模型是死的,业务是活的。在实践过程中,还会有很多的变体,万变不离其宗,只要掌握了这几种模型的核心,任何变体都可以随心所欲。