一般来说,我们在设计与人有交互的系统时,如果涉及到多用户能对同类资源进行操作的时候,就会有区分权限的需求了。
ACL(Access Control List)
ACL
是最早也是最基本的一种访问控制机制,
它的原理非常简单:每一项资源,都配有一个列表,这个列表记录的就是哪些用户可以对这项资源执行CRUD
中的那些操作。
当系统试图访问这项资源时,会首先检查这个列表中是否有关于当前用户的访问权限,从而确定当前用户可否执行相应的操作。
如:
1 | Alice -> read:article, update:article |
通过ACL表,我们可以很容易的使用程序判断出用户的权限。我们在设计RESTFUL
接口时,权限可以设计为:
1 | Alice -> GET /article, PUT /article |
ACL
缺点也是很明显的,首先需要维护大量的访问权限列表,它在性能上有明显的缺陷。
另外,对于拥有大量用户与众多资源的应用,管理访问控制列表本身就变成非常繁重的工作。
DAC(Discretionary Access Control)
被操作对象,根据访问控制规则,来判断操作主体可对操作对象做哪些操作,比如只读或者是可写的权限。 而自主的含义,则是拥有某种权限的用户,可以把权限赋予其他用户。
这种设计最常见的应用就是文件系统的权限设计,如微软的NTFS。
DAC最大缺陷就是对权限控制比较分散,不便于管理,比如无法简单地将一组文件设置统一的权限开放给指定的一群用户。
MAC(Mandatory Access Control)
MAC是为了弥补DAC权限控制过于分散的问题而诞生的。 在MAC的设计中,每一个对象都都有一些权限标识,每个用户同样也会有一些权限标识, 而用户能否对该对象进行操作取决于双方的权限标识的关系,这个限制判断通常是由系统硬性限制的。
MAC非常适合机密机构或者其他等级观念强烈的行业,如军事系统,但对于类似商业服务系统,则因为不够灵活而不能适用。
RBAC(Role-Based Access Control)
RBAC
是把用户按角色进行归类,通过用户的角色来确定用户能否针对某项资源进行某项操作。
RBAC
相对于ACL最大的优势就是它简化了用户与权限的管理,通过对用户进行分类,使得角色与权限关联起来,而用户与权限变成了间接关联。
1 | ArticleEditor -> read:article, update:article |
但是它也有自身的缺点,那就是由于权限是以角色为载体分配的,如果某一角色下的个别用户需要进行特别的权限定制, 如同加入一些其他角色的小部分权限或去除当前角色的一些权限时,RBAC就无能为力了,因为RBAC对权限的分配是角色为单位的。
ABAC(Attribute-Based Access Control)
不同于常见的将用户通过某种方式关联到权限的方式, ABAC则是通过动态计算一个或一组属性是否满足某种条件来进行授权判断的(可以编写简单的逻辑)。 属性通常来说分为四类:用户属性(如用户年龄),环境属性(如当前时间),操作属性(如读取)和对象属性(如一篇文章,又称资源属性), 所以理论上能够实现非常灵活的权限控制,几乎能满足所有类型的需求。
例如:
- 一个用户可以查看它所在部门内部的文档;
- 一个用户可以编辑一个处于草稿阶段的文档;
- 早上9点上班之前,禁止用户查看任何文档;
由此可以看出ABAC
非常的灵活,但是实现也是非常的难。
这其中涉及到逻辑的动态执行,数据动态过滤等,更加具体就是动态拼接SQL语句(使用ORM的话就是动态组装对应ORM的查询语句)。
根据配置的规则,最后解析出来可能是各种Sql语句:<
、>
、=
、like
、in
、not in
等等。
所以,ABAC
的缺点非常明显,那就是它的复杂性。
每次都要解析规则,对程序的性能也造成的影响,就算使用缓存,命中的概率也是非常的小,因为很多因素都是动态的。
所以,如果需要根据属性做权限判断的场景不是很多的话,建议使用RBAC
。