术语

用户

发起操作的主体。

对象(Subject)

指操作所针对的客体对象,比如订单数据或图片文件。

权限控制表 (ACL: Access Control List)

用来描述权限规则或用户和权限之间关系的数据表。

权限 (Permission)

用来指代对某种对象的某一种操作,例如“添加文章的操作”。

权限标识

权限的代号,例如用“ARTICLE_ADD”来指代“添加文章的操作”权限。

常见设计模式

自主访问控制(DAC: Discretionary Access Control)

系统会识别用户,然后根据被操作对象(Subject)的权限控制列表(ACL: Access Control List)或者权限控制矩阵(ACL: Access Control Matrix)的信息来决定用户的是否能对其进行哪些操作,例如读取或修改。

而拥有对象权限的用户,又可以将该对象的权限分配给其他用户,所以称之为“自主(Discretionary)”控制。

这种设计最常见的应用就是文件系统的权限设计,如微软的NTFS。

DAC最大缺陷就是对权限控制比较分散,不便于管理,比如无法简单地将一组文件设置统一的权限开放给指定的一群用户。

Windows的文件权限

强制访问控制(MAC: Mandatory Access Control)

MAC是为了弥补DAC权限控制过于分散的问题而诞生的。在MAC的设计中,每一个对象都都有一些权限标识,每个用户同样也会有一些权限标识,而用户能否对该对象进行操作取决于双方的权限标识的关系,这个限制判断通常是由系统硬性限制的。比如在影视作品中我们经常能看到特工在查询机密文件时,屏幕提示需要“无法访问,需要一级安全许可”,这个例子中,文件上就有“一级安全许可”的权限标识,而用户并不具有。

MAC非常适合机密机构或者其他等级观念强烈的行业,但对于类似商业服务系统,则因为不够灵活而不能适用。

RedHat MLS

Red Hat: MLS

基于角色的访问控制(RBAC: Role-Based Access Control)

因为DAC和MAC的诸多限制,于是诞生了RBAC,并且成为了迄今为止最为普及的权限设计模型。

RBAC在用户和权限之间引入了“角色(Role)”的概念(暂时忽略Session这个概念):

如图所示,每个用户关联一个或多个角色,每个角色关联一个或多个权限,从而可以实现了非常灵活的权限管理。角色可以根据实际业务需求灵活创建,这样就省去了每新增一个用户就要关联一遍所有权限的麻烦。简单来说RBAC就是:用户关联角色,角色关联权限。另外,RBAC是可以模拟出DAC和MAC的效果的。

例如数据库软件MongoDB便是采用RBAC模型,对数据库的操作都划分成了权限(MongoDB权限文档):

权限标识 说明
find 具有此权限的用户可以运行所有和查询有关的命令,如:aggregate、checkShardingIndex、count等。
insert 具有此权限的用户可以运行所有和新建数据有关的命令:insert和create等。
collStats 具有此权限的用户可以对指定database或collection执行collStats命令。
viewRole 具有此权限的用户可以查看指定database的角色信息。

基于这些权限,MongoDB提供了一些预定义的角色(MongoDB预定义角色文档,用户也可以自己定义角色):

角色 find insert collStats viewRole
read
readWrite
dbAdmin
userAdmin

最后授予用户不同的角色,就可以实现不同粒度的权限分配了。

目前市面上绝大部分系统在设计权限系统时都采用RBAC模型。然而也有的系统错误地实现了RBAC,他们采用的是判断用户是否具有某个角色而不是判断权限,例如以下代码:

<?phpif ($user->hasRole('hr')) {// 执行某种只有“HR”角色才能做的功能,例如给员工涨薪…// ...
}

如果后期公司规定部门经理也可以给员工涨薪,这时就不得不修改代码了。

以上基本就是RBAC的核心设计(RBAC Core)。而基于核心概念之上,RBAC规范还提供了扩展模式。

角色继承(Hierarchical Role)

带有角色继承的RBAC。图片来自Apache Directory

顾名思义,角色继承就是指角色可以继承于其他角色,在拥有其他角色权限的同时,自己还可以关联额外的权限。这种设计可以给角色分组和分层,一定程度简化了权限管理工作。

职责分离(Separation of Duty)

为了避免用户拥有过多权限而产生利益冲突,例如一个篮球运动员同时拥有裁判的权限(看一眼就给你判犯规狠不狠?),另一种职责分离扩展版的RBAC被提出。

职责分离有两种模式:

  • 静态职责分离(Static Separation of Duty):用户无法同时被赋予有冲突的角色。
  • 动态职责分离(Dynamic Separation of Duty):用户在一次会话(Session)中不能同时激活自身所拥有的、互相有冲突的角色,只能选择其一。

!

RBAC 2

静态职责分离。图片来自Apache Directory

RBAC 3

动态职责分离。图片来自Apache Directory

讲了这么多RBAC,都还只是在用户和权限之间进行设计,并没有涉及到用户和对象之间的权限判断,而在实际业务系统中限制用户能够使用的对象是很常见的需求。例如华中区域的销售没有权限查询华南区域的客户数据,虽然他们都具有销售的角色,而销售的角色拥有查询客户信息的权限。

那么我们应该怎么办呢?

用户和对象的权限控制

在RBAC标准中并没有涉及到这个内容(RBAC基本只能做到对一类对象的控制),但是这里讲几种基于RBAC的实现方式。

首先我们看看PHP框架Yii 1.X的解决方案(2.X中代码更为优雅,但1.X的示例代码更容易看明白):

<?php$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的文章具有编辑的权限,代码可能是这样的:

<?php// 假设articleId是动态获取的
$articleId = 123;if ($user->can("article:edit:{$articleId}")) {// ...
}

而给用户授权则有多种方式可以选择:

<?php// 允许用户编辑Id为123的文章
$user->grant('article:edit:123');// 使用通配符,允许用户编辑所有文章
$user->grant('article:edit:*');

虽然不及Yii方案的灵活,但某些场景下这样就够用了。

如果大家还有更好的方案,欢迎在评论中提出。

基于属性的权限验证(ABAC: Attribute-Based Access Control)

ABAC被一些人称为是权限系统设计的未来。

不同于常见的将用户通过某种方式关联到权限的方式,ABAC则是通过动态计算一个或一组属性来是否满足某种条件来进行授权判断(可以编写简单的逻辑)。属性通常来说分为四类:用户属性(如用户年龄),环境属性(如当前时间),操作属性(如读取)和对象属性(如一篇文章,又称资源属性),所以理论上能够实现非常灵活的权限控制,几乎能满足所有类型的需求。

例如规则:“允许所有班主任在上课时间自由进出校门”这条规则,其中,“班主任”是用户的角色属性,“上课时间”是环境属性,“进出”是操作属性,而“校门”就是对象属性了。为了实现便捷的规则设置和规则判断执行,ABAC通常有配置文件(XML、YAML等)或DSL配合规则解析引擎使用。XACML(eXtensible Access Control Markup Language)是ABAC的一个实现,但是该设计过于复杂,我还没有完全理解,故不做介绍。

总结一下,ABAC有如下特点:

  1. 集中化管理
  2. 可以按需实现不同颗粒度的权限控制
  3. 不需要预定义判断逻辑,减轻了权限系统的维护成本,特别是在需求经常变化的系统中
  4. 定义权限时,不能直观看出用户和对象间的关系
  5. 规则如果稍微复杂一点,或者设计混乱,会给管理者维护和追查带来麻烦
  6. 权限判断需要实时执行,规则过多会导致性能问题

一文搞定权限设计模型(RBAC,ABAC)超详细图文解析相关推荐

  1. 一文搞定子网划分!子网掩码!超详细例题解析!

    子网划分理论基础 为什么进行子网划分 减少网络流量,无论什么样的流量,我们都希望它少些,网络流量亦如此.如果没有可信赖的路由器,网络流量可能导致整个网络停顿,但有了路由器后,大部分流量都将呆在本地网络 ...

  2. java权限精确到按钮_搞定权限设计1-页面按钮控制(精确到某个用户和某个按钮)...

    每个系统都离不开权限控制,这里来说说页面上控制到按钮的思路,仅提供思路: 使用 角色 + 资源(菜单和菜单对应页面上的按钮)+ 授权的方式. 1  定义角色与用户: 假定这里我们只控制到角色这一层次, ...

  3. 一文搞定电子设计的静电放电(ESD)问题

    冬天来了,又到触电时刻!和静电亲密接触的瞬间,可以弹出好几米.不止生活中,我们的电子电路中也"隐藏"静电,你知道么? 人类认识静电放电(ESD)的心路历程 顾名思义,静电就是静止不 ...

  4. 20分钟搞定平衡二叉树(AVL树)【超详细】

    文章目录 一.树结构入门 1.什么是树? 2.树结构常用术语 3.二叉搜索树 二.平衡二叉树(AVL树) 1. AVL树简介 2. 失衡二叉排序树的分析与调整 3. 为什么有了平衡树还需要红黑树? 一 ...

  5. 【嵌入式开发-AD19】六文搞定Altium Designer-第一章:AD介绍及原理图库的创建

    [嵌入式开发-AD19]六文搞定Altium Designer-第一章:AD介绍及原理图库的创建 在文章的开头我想首先简单介绍一下国产全免费EDA软件,嘉立创EDA.嘉立创EDA拥有网页版和安装版两种 ...

  6. 【语义分割】综述——一文搞定语义分割

    本文记录了博主阅读的关于语义分割(Semantic Segmentation)的综述类文章的笔记,更新于2019.02.19. [语义分割]综述--一文搞定语义分割 参考文献网址 An overvie ...

  7. php带参数单元测试_一文搞定单元测试核心概念

    基础概念 单元测试(unittesting),是指对软件中的最小可测试单元进行检查和验证,这里的最小可测试单元通常是指函数或者类.单元测试是即所谓的白盒测试,一般由开发人员负责测试,因为开发人员知道被 ...

  8. 基于角色的权限控制模型RBAC

    本文来说下基于角色的权限控制模型RBAC 文章目录 概述 RBAC权限模型简介 RBAC的演化进程 用户与权限直接关联 一个用户拥有一个角色 一个用户一个或多个角色 页面访问权限与操作权限 数据权限 ...

  9. html百度首页制作视频,韩顺平 轻松搞定网页设计 html+css+js

    韩顺平老师的教程影响着一代又一代的学子们,他的视频教程确实做的很经典,不论是java.php还是网页设计,都有出彩的地方.这里,小编给大家分享韩顺平老师的轻松搞定网页设计教程,绝对完整,全部存于百度网 ...

  10. 最强绘图AI:一文搞定Midjourney(附送咒语)

    最强绘图AI:一文搞定Midjourney(附送咒语) Midjourney官网:https://www.midjourney.com 简介 Midjourney是目前效果最棒的AI绘图工具.访问Mi ...

最新文章

  1. 开辟经济发展的第二战场
  2. CORS 跨域-同源
  3. 1400协议是什么和28181区别_公安三所标准 跟GB28181标准 有什么 区别?
  4. 最详细的手机资料名词术语解释
  5. 2020软考架构设计师真题
  6. spring5.X源码构建
  7. Ubuntu常用命令及git常用命令
  8. 在windows7下给vs2015配置dirent.h头文件
  9. Java中什么不是线程状态_并发基础(四) java中线程的状态
  10. 大数据的核心价值是什么
  11. Qt使用QChart制作多路虚拟示波器
  12. leapmotion 导入 unity 3D 教程
  13. windowsXP sp2 to sp3 的升级包
  14. wsl 搭建 ubantu环境
  15. 湖北计算机考试条列,湖北省计算机考试大纲及考生须知
  16. 关于直播类app中的推流、拉流技术
  17. oracle 大数据量分页查询
  18. Jenkins 如何与 Kubernetes 集群的 Tekton Pipeline 交互?
  19. 170311 Python-steam游戏排行爬虫
  20. php kafka使用

热门文章

  1. 天邑ty400 wifi6路由 安装第三方扩展 Entware
  2. 阿里前端电话面试问题
  3. 学习笔记(8)之VelocityTracker
  4. rup软件测试案例,胖子说RUP - 软件测试网 _领测软件测试网站-中国软件测试技术第一门户...
  5. 软件测试初学者如何编写Jmeter测试脚本?
  6. Oracle12C如何启动PDB数据库
  7. a0图框标题栏尺寸_机械制图标准中规定的标题栏尺寸
  8. ROS与Arduino:ros_arduino_bridge功能包的使用解读
  9. aspupload 上传组件下载
  10. 自动升级WordPress失败解决方法