本文讨论以角色概念进行的权限管理策略及主要以基于角色的机制进行权限管理是远远不够的。同时我将讨论一种我认为更好的权限管理方式。

1、什么是角色

当说到程序的权限管理时,人们往往想到角色这一概念。角色是代表一系列可执行的操作或责任的实体,用于限定你在软件系统中能做什么、不能做什么。用户帐号往往与角色相关联,因此,一个用户在软件系统中能做什么取决于与之关联的各个角色。

例如,一个用户以关联了”项目管理员”角色的帐号登录系统,那这个用户就可以做项目管理员能做的所有事情――如列出项目中的应用、管理项目组成员、产生项目报表等。

从这个意义上来说,角色更多的是一种行为的概念:它表示用户能在系统中进行的操作集合。

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

既然角色代表了可执行的操作这一概念,一个合乎逻辑的做法是在软件开发中使用角色来控制对软件功能和数据的访问。你可能已经猜到,这种权限控制方法就叫基于角色的访问控制(Role-Based Access Control),或简称为RBAC。

有两种正在实践中使用的RBAC访问控制方式:隐式(模糊)的方式和显示(明确)的方式。

今天依旧有大量的软件应用是使用隐式的访问控制方式。但我肯定的说,显示的访问控制方式更适合于当前的软件应用。

3、隐式的访问控制

前面提到,角色代表一系列的可执行的操作。但我们如何知道一个角色到底关联了哪些可执行的操作呢?

答案是:目前的大多数应用,你并能不明确的知道一个角色到底关联了哪些可执行操作。可能你心里是清楚的(你知道一个有”管理员”角色的用户可以锁定用户帐号、进行系统配置;一个关联了”消费者”这一角色的用户可在网站上进行商品选购),但这些系统并没有明确定义一个角色到底包含了哪些可执行的行为。

拿”项目管理员”来说,系统中并没有对”项目管理员”能进行什么样的操作进行明确定义,它仅是一个字符串名词。开发人员通常将这个名词写在程序里以进行访问控制。例如,判断一个用户是否能查看项目报表,程序员可能会编码如下:

代码块1.隐式地基于角色的权限控制:

if (user.hasRole("Project Manager")) {
//show the project report button
} else {
//don't show the button
}

在上面的示例代表中,开发人员判断用户是否有”项目管理员”角色来决定是否显示查看项目报表按钮。请注意上面的代码,它并没有明确语句来定义”项目管理员”这一角色到底包含哪些可执行的行为,它只是假设一个关联了项目管理员角色的用户可查看项目报表,而开发人员也是基于这一假设来写if/else语句。

4、脆弱的权限策略

像上面的权限访问控制是非常脆弱的。一个极小的权限方面的需求的变动都可能导致上面的代码需要重新修改。

举例来说,假如某一天这个开发团队被告知:“哦,顺便说一下,我们需要一个’部门管理员’角色,他们也可以查看项目报表。请做到这一点。”

这种情况下,开发人员需要找到上面的代码块并将其修改为:

代码块2.修改过的隐式的基于角色的权限控制:

if (user.hasRole("Project Manager") || user.hasRole("Department Manager") ) {
//show the project report button
} else {
//don't show the button
}

随后,开发人员需要更新他的测试用例、重新编译系统,还可能需要重走软件质量控制(QA)流程,然后再重新部署上线。这一切仅仅是因为一个微小的权限方面的需求变动!

后面如果需求方又回来告诉你说我们又有另一个角色可查看报表,或是前面关于”部门管理员可查看报表”的需求不再需要了,岂不把人累死了。

如果需求方要求动态地创建、删除角色以便他们自己配置角色,又该如何应对呢?

像上面的情况,这种隐式的(静态字符串)形式的基于角色的访问控制方式难以满足需求。理想的情况是如果权限需求变动不需要修改任何代码。怎样才能做到这一点呢?

5、显式地访问控制:更好的选择

从上面的例子我们看到,当权限需求发生变动时,隐式的权限访问控制方式会给程序开发带来沉重的负担。如果能有一种方式在权限需求发生变化时不需要去修改代码就能满足需求那就好了。理解的情况是,即使是正在运行的系统,你也可以修改权限策略却又不影响最终用户的使用。当你发现某些错误的或危险的安全策略时,你可以迅速地修改策略配置,同时你的系统还能正常使用,而不需要重构代码重新部署系统。

怎样才能达到上面的理想效果呢?我们可以通过显式的(明确的)界定我们在应用中能做的操作来进行。

回顾上面隐式的权限控制的例子,思考一下这些代码最终的目的,想一下它们最终是要做什么样的控制?

从根本上说,这些代码最终是在保护资源(项目报表),是要界定一个用户能对这些资源进行什么样的操作(查看/修改)。当我们将权限访问控制分解到这种最原始的层次,我们就可以用一种更细粒度(更富有弹性)的方式来表达权限控制策略。

我们可以修改上面的代码块,以基于资源的语义来更有效地进行权限访问控制:

代码块3.显式的权限控制:

if (user.isPermitted("projectReport:view:12345")) {
//show the project report button
} else {
//don't show the button
}

上面的例子中,我们可明确地看到我们是在控制什么。不要太在意冒号分隔的语法,这仅是一个例子,重点是上面的语句明确地表示了“如果当前用户允许查看编号为12345的项目报表,则显示项目报表按钮”。也就是说,我们明确地说明了一个用户帐号可对一个的资源实例进行的具体的操作。

6、为什么说这种方式更好

上面最后的示例代码块与前面的代码的主要区别:最后的代码块是基于什么是受保护的, 而不是谁可能有能力做什么。看似简单的区别,但后者对系统开发及部署有着深刻的影响:

  • 更少的代码重构:我们是基于系统的功能(系统的资源及对资源的操作)来进行权限控制,而相应来说,系统的功能需求一旦确定下来后,一段时间内对它的改动相应还是比较少的。只是当系统的功能需求改变时,才会涉及到权限代码的改变。例如上面提到的查看项目报表的功能,显式的权限控制方式不会像传统隐式的RBAC权限控制那样因不同的用户/角色要进行这个操作就需要重构代码;只要这个功能存在,显式的方式的权限控制代码是不需要改变的。
  • 更直观:保护资源对象、控制对资源对象的操作(对象及对象的行为),这样的权限控制方式更符合人们的思想习惯。正因为符合这种直观的思维方式,面向对象的编辑思想及REST通信模型变得非常成功。
  • 更有弹性:上面的示例代码中没有写死哪些用户、组或角色可对资源进行什么操作。这意味着它可支持任何安全模型的设计。例如,可以将操作(权限)直接分配给用户 ,或者他们可以被分配到一个角色,然后再将角色与用户关联,或者将多个角色关联到组(group)上,等等。你完全可以根据应用的特点定制权限模型。
  • 外部安全策略管理:由于源代码只反映资源和行为,而不是用户、组和角色,这样资源/行为与用户、组、角色的关联可以通过外部的模块或专用工具或管理控制台来完成。这意味着在权限需求变化时,开发人员并不需要花费时间来修改代码,业务分析师甚至最终用户就可以通过相应的管理工具修改权限策略配置。
  • 可在运行环境做修改:因为基于资源的权限控制代码并不依赖于行为的主体(如组、角色、用色),你并没有将行为的主体的字符名词写在代码中,所以你甚至可以在程序运行的时候通过修改主体能对资源进行的操作这样一些方式,通过配置的方式就可应对权限方面需求的变动,再也不需要像隐式的RBAC方式那样需要重构代码。

7、RBAC新解:Resource-Based Access Control

对于上面列出的诸多好处,我重点要说是这种显式的机制带给我们的富有弹性的权限模型。

如果你仍想保留或模拟传统的基于角色的权限访问控制,你可以将权限(可执行的操作)直接分配给某个角色。这种情况下,你依旧是在使用基于角色的权限访问控制方式(不同之处在于你需要明确地界定角色中的权限,而不是传统的使用角色字符串隐式地进行权限控制)。

但在这种新的模型下,已不必再局限于角色了。你可以将权限直接分配给用户、组或其它你觉得可以的对象。

因为上面显式地、基于资源的权限访问控制的诸多好处,或许可以给RBAC一个新的定义:“Resource-Based Access Control”。

8、现实世界的例子:Apache Shiro

如果你好奇现实世界有没有被多个系统使用的基于资源的权限控制框架,你可以了解一下Apache Shiro。它是一个java平台的现代权限管理框架。通过它的权限(Permission)概念,Shiro很好地支持基于资源的权限访问控制。

当然,并不需要借用Shiro来理解本文所说的一些概念,但Shiro对理解本文所讨论的概念及示例有一定的帮助。

权限管理系统(五):RBAC新解,基于资源的权限管理的更多相关文章

  1. RBAC: K8s基于角色的权限控制

    文章目录 RBAC: K8s基于角色的权限控制 ServiceAccount.Role.RoleBinding Step 1:创建一个ServiceAccount,指定namespace Step 2 ...

  2. ABP module-zero +AdminLTE+Bootstrap Table+jQuery权限管理系统第十二节--小结,Bootstrap Table之角色管理

    返回总目录:ABP+AdminLTE+Bootstrap Table权限管理系统一期 很多人说ABP不适合高并发大型,有一定的道理,但是我觉得还是可以的,就看架构师的能力了,哈哈,我之前公司就是ABP ...

  3. ABP+AdminLTE+Bootstrap Table权限管理系统第十一节--bootstrap table之用户管理列表

    这张开始bootstrap table,引入项目有两种方法,一种是直接去官网下载 地址:http://bootstrap-table.wenzhixin.net.cn/ 另一种是Nuget引入. 然后 ...

  4. 基于资源的权限系统-API设计

    概述 权限系统需要和别的系统集成,因此,良好的API是易用性的保证. 这里只设计一些权限相关的核心 API,关于用户,组织,导入导出之类的后续再逐步补充 API 设计 围绕权限有以下 4 类 API: ...

  5. 基于RBAC模型的通用企业权限管理系统

    1. 为什么我们需要基于RBAC模型的通用企业权限管理系统 管理信息系统是一个复杂的人机交互系统,其中每个具体环节都可能受到安全威胁.构建强健的权限管理系统,保证管理信息系统的安全性是十分重要的.权限 ...

  6. 分享一个html+js+ashx+easyui+ado.net权限管理系统

    EasyUI.权限管理 这是个都快被搞烂了的组合,但是easyui的确好用,权限管理在项目中的确实用.一直以来博客园里也不少朋友分享过,但是感觉好的要不没源码,要不就是过度设计写的太复杂看不懂,也懒得 ...

  7. html+js+ashx+easyui+ado.net权限管理系统

    分享一个html+js+ashx+easyui+ado.net权限管理系统   EasyUI.权限管理 这是个都快被搞烂了的组合,但是easyui的确好用,权限管理在项目中的确实用.一直以来博客园里也 ...

  8. 权限组件之rbac

    rbac:基于角色的权限访问控制(Role-Based Access Control). rbac的主要流程:给每个角色赋予不同的权限,是这个角色的员工都有这个角色的所有权限.一个角色可以有多个人员担 ...

  9. 【shiro】(2)---基于RUL的权限管理

    基于RUL的权限管理 我想在写shiro权限管理认证前,先来一个基于URL实现的权限管理控制. 一.基于URI的权限业务逻辑  实现思路:       将系统操作的每个url配置在权限表中,将权限对应 ...

随机推荐

  1. CentOS yum时出现"Could not retrieve mirrorlist"

    问题描述: CentOS 6.x minimal(最小化) 安装, CentOS yum install net-tools 时出现"Could not retrieve mirrorlis ...

  2. Linux chattr 命令

    不让用户修改.删除文件等,使用 chattr保护 chattr命令的用法:chattr [ -RV ] [ -v version ] [ mode ] files… 最关键的是在[mode]部分,[m ...

  3. Inno Setup入门(十)——操作注册表

    有些程序需要随系统启动,或者需要建立某些文件关联等问题,这些都是通过在安装程序中对注册表进行操作的结果.Inno Setup中通过[registry]段实现对注册表的操作. 本段说明: 参数列表: 参 ...

  4. glog的使用

    主要还是看官方文档吧 win32下,把#define GLOG_NO_ABBREVIATED_SEVERITIES 放到#include <windows.h>之前,具体说明文档中有说. ...

  5. Linux-socket的close和shutdown区别及应用场景

    shutdown的定义 #include<sys/socket.h> int shutdown(int sockfd,int how); how的方式有三种分别是: SHUT_RD(0): ...

  6. hibernate实现多表联合查询

    转自:http://blog.sina.com.cn/s/blog_67b9ad8d01010by1.html 以前用sql实现联合查询 是非常简单的事,只需要写sql语句就可以,第一次遇到hiber ...

  7. [Spring学习笔记 5 ] Spring AOP 详解1

    知识点回顾:一.IOC容器---DI依赖注入:setter注入(属性注入)/构造子注入/字段注入(注解 )/接口注入 out Spring IOC容器的使用: A.完全使用XML文件来配置容器所要管理 ...

  8. 【LeetCode】215. Kth Largest Element in an Array (2 solutions)

    Kth Largest Element in an Array Find the kth largest element in an unsorted array. Note that it is t ...

  9. 使用itext直接替换PDF中的文本

    直接说问题,itext没有直接提供替换PDF中文本的接口(查看资料得到的结论是PDF不支持这种操作),不过存在解决思路:在需要替换的文本上覆盖新的文本.按照这个思路我们需要解决以下几个问题: itex ...

  10. 【java】break outer,continue outer的使用

    break默认是结束当前循环,有时我们在使用循环时,想通过内层循环里的语句直接跳出外层循环,java提供了使用break直接跳出外层循环,此时需要在break后通过标签指定外层循环.java中的标签是 ...