发起操作的主体。
主题
指操作所针对的对象对象,例如订单数据或图像文件。
ACL:访问控制列表
用于描述权限规则或用户与权限之间关系的数据表。
允许
用来指对某个对象的某种操作,例如“添加文章的操作”。
权限ID
权限的代号2d素材,例如使用“ARTICLE_ADD”来指代“添加文章的操作”权限。
常见设计模式自主访问控制(DAC:Discretionary Access Control)
系统会识别用户,然后根据访问控制列表(ACL)或访问控制矩阵(ACL:Access Control Matrix)中的信息来判断该用户是否可以对主体(Subject)进行操作。 例如,读取或修改。
拥有对象权限的用户可以将对象权限分配给其他用户权限管理设计角色游戏图片,因此称为“自由裁量”控制。
这种设计最常见的应用就是文件系统的权限设计,比如微软的NTFS。
DAC最大的缺陷是权限控制比较分散,难以管理。 例如,它不能简单地为一组文件设置统一的权限并向指定的一组用户打开。
Windows 文件权限
强制访问控制(MAC:强制访问控制)
MAC的诞生就是为了弥补DAC权限控制过于分散的问题。 在MAC的设计中,每个对象都有一些权限标识符,每个用户也有一些权限标识符。 用户是否可以操作该对象取决于双方的权限标识之间的关系。 这种限制判断通常不受系统限制。 例如,在影视作品中,我们经常看到特工查询机密文件时,屏幕提示“无法访问,需要一级安全许可”。 在本例中,文件上有“1级安全许可”的权限标记,而用户没有该权限标记。
MAC非常适合保密机构或者其他层级观念较强的行业,但对于类似的商业服务系统则无法应用,因为它不够灵活。
红帽MLS
红帽:MLS
基于角色的访问控制(RBAC:基于角色的访问控制)
由于DAC和MAC的诸多限制,RBAC诞生了,并成为迄今为止最流行的权限设计模型。
RBAC引入了用户和权限之间“角色”的概念(暂时忽略Session的概念):
如图所示,每个用户关联一个或多个角色,每个角色关联一个或多个权限,从而实现非常灵活的权限管理。 可以根据实际业务需求灵活创建角色,免去了每次添加新用户时关联所有权限的麻烦。 简单来说,RBAC的意思是:用户与角色关联,角色与权限关联。 另外,RBAC可以模拟DAC和MAC的效果。
例如数据库软件MongoDB采用RBAC模型,对数据库的操作分为权限(MongoDB权限文档):
权限标识说明
寻找
拥有此权限的用户可以运行所有与查询相关的命令权限管理设计角色,例如aggregate、checkShardingIndex、count等。
插入
具有此权限的用户可以运行与创建新数据相关的所有命令:插入、创建等。
科尔统计
具有此权限的用户可以对指定的数据库或集合执行collStats 命令。
视图角色
具有此权限的用户可以查看指定数据库的角色信息。
……
基于这些权限,MongoDB提供了一些预定义的角色(MongoDB预定义角色文档,用户也可以定义自己的角色):
rolefindinsertcollStatsviewRole...
读
✔
✔
……
读写
✔
✔
✔
……
数据库管理员
✔
✔
……
用户管理
✔
……
最后,通过赋予用户不同的角色,可以实现不同粒度的权限分配。
目前市场上大多数系统在设计权限系统时都采用RBAC模型。 然而,有些系统错误地实现了 RBAC。 它们用于确定用户是否具有特定角色,而不是确定权限。 例如,以下代码:
if ($user->hasRole('hr')) {// 执行某种只有“HR”角色才能做的功能,例如给员工涨薪…// ...
}
如果公司后来规定部门经理也可以给员工加薪,那么代码就得修改了。
以上基本上就是RBAC(RBAC Core)的核心设计了。 在核心概念的基础上,RBAC规范还提供了扩展模式。
等级角色
具有角色继承的 RBAC。 图片来自 Apache 目录
顾名思义,角色继承意味着角色可以继承其他角色。 在拥有其他角色权限的同时,还可以关联额外的权限。 这样的设计可以对角色进行分组和分层,一定程度上简化了权限管理。
职责分离
为了避免用户权限过多造成利益冲突,比如篮球运动员还拥有裁判员的权限(他会一眼就判你犯规吗?),职责分离的RBAC的另一个扩展版本被提议。
职责分离有两种模式:
角色控制2
静态职责分离。 图片来自 Apache 目录
角色控制3
动态职责分离。 图片来自 Apache 目录
讲了这么多RBAC,它只是设计在用户和权限之间,并不涉及用户和对象之间权限的判断。 在实际的业务系统中,限制用户可以使用的对象是很常见的需求。 例如,华中区域的销售没有查询华南区域客户数据的权限,虽然他们都有销售角色,并且销售角色有查询客户信息的权限。
那么我们应该做什么呢?
用户和对象权限控制
这个内容在RBAC标准中并没有涵盖(RBAC基本上只能控制一类对象),但这里介绍几种基于RBAC的实现方法。
首先我们看一下PHP框架Yii 1.X的解决方案(2.X中的代码更加优雅,但是1.X的示例代码更容易理解):
$auth=Yii::app()->authManager;$auth->createOperation('createPost','create a post');
$auth->createOperation('readPost','read a post');
$auth->createOperation('updatePost','update a post');
$auth->createOperation('deletePost','delete a post');// 主要看这里。
// 这里创建了一个名为`updateOwnPost`的权限,并且写了一段代码用来检验用户是否为该帖子的作者
$bizRule='return Yii::app()->user->id==$params["post"]->authID;';
$task=$auth->createTask('updateOwnPost','update a post by author himself',$bizRule);
$task->addChild('updatePost');$role=$auth->createRole('reader');
$role->addChild('readPost');$role=$auth->createRole('author');
$role->addChild('reader');
$role->addChild('createPost');
$role->addChild('updateOwnPost');$role=$auth->createRole('editor');
$role->addChild('reader');
$role->addChild('updatePost');$role=$auth->createRole('admin');
$role->addChild('editor');
$role->addChild('author');
$role->addChild('deletePost');
实现效果:
Yii 1.X 权限图
图片来自Yii官方Wiki
在这个Yii官方的例子中,updateOwnPost在判断用户是否有updatePost权限的基础上,进一步判断用户是否有操作这个特定对象的权限,并且这个判断逻辑是通过代码来设置的,非常灵活。
然而,大多数时候我们并不需要这样的灵活性,这会带来额外的开发和维护成本,而另一种基于模式匹配规则的对象权限控制可能更适合。 例如,判断用户是否对ID为123的文章有编辑权限,代码可能如下:
// 假设articleId是动态获取的
$articleId = 123;if ($user->can("article:edit:{$articleId}")) {// ...
}
授权用户的方式有多种可供选择:
// 允许用户编辑Id为123的文章
$user->grant('article:edit:123');// 使用通配符,允许用户编辑所有文章
$user->grant('article:edit:*');
虽然不如 Yii 方案灵活,但在某些场景下已经足够了。
如果您有更好的解决方案,请在评论中提出。
基于属性的访问控制(ABAC:基于属性的访问控制)
ABAC 被一些人称为权限系统设计的未来。
与常见的通过某种方式将用户与权限关联起来的方式不同,ABAC通过动态计算一个或一组属性来判断是否满足某些条件(可以写简单的逻辑)来进行授权判断。 属性一般分为四类:用户属性(如用户年龄)、环境属性(如当前时间)、操作属性(如阅读)和对象属性(如文章,也称为资源属性),所以理论上可以实现非常灵活的权限控制,满足几乎所有类型的需求。
例如规定:“允许所有班主任在上课时间自由进出学校”。 其中,“班主任”为用户的角色属性,“上课时间”为环境属性,“进出”为操作属性,“校门”为对象。 属性。 为了实现方便的规则设置和规则判断执行,ABAC通常有配置文件(XML、YAML等)或DSL来配合规则解析引擎。 XACML(eXtensible Access Control Markup Language)是ABAC的一种实现,但是设计太复杂,我还没有完全理解,所以就不介绍了。
综上所述,ABAC具有以下特点:
集中管理可以按需实现不同粒度的权限控制,无需预先定义判断逻辑,降低了权限系统的维护成本。 尤其是在需求频繁变化的系统中定义权限时,无法直观地看到用户和对象之间的关系。 如果关系规则稍复杂或者设计混乱,就会给管理者维护和追溯带来麻烦。 权限判断需要实时执行。 太多的规则会导致性能问题。