1. 权限体系概要
权限是所有应用都需要考虑的问题。从方向上来说,权限可以分为功能权限和数据权限,功能权限指你能发起什么事件,数据权限指你能看到哪些数据。合起来就是你能看到哪些数据,对他们分别能发起哪些事件。
1.1 功能权限
功能权限有很多理论模型,经常谈到的有DAC,MAC,RBAC,ABAC,可以看到都是AC结尾,AC代表Access Control。其中以RBAC在实际系统中应用最多。
1.1.1 主动访问控制:DAC:Discretionary Access Control
DAC有两个关键点:1资源默认只有创建者拥有全部权限;2资源由谁创建,该资源的权限就由谁分配;
DAC是这样工作的,系统首先会识别用户,然后根据用户要操作的资源,去查询他是否能做操作,比如查看和编辑。最典型的例子,就是Windows的文件权限控制:
DAC的缺点在于:权限控制过于分散,不方便管理。
1.1.2 强制访问控制:MAC:Mandatory Access Control
MAC有四个关键点:1资源和用户都有权限等级;2资源和用户的权限等级全部由管理员控制;3用户权限等级高于或等于资源时,才具有操作权限;4下读上写。
其中下读上写,是出于保密的考虑。具体是指用户只能阅读权限等于或低于自身的资源,只能创建和编辑权限等于或高于自身的资源。举个例子,权限等级1最低,5最高,用户A的权限是3,他可以看到等级为1,2,3的文件,只能创建和编辑3,4,5的文件。
MAC通常用在保密性比较高的政治军事系统中,比如FBI的文件保密系统。缺点在于太过严格而导致不够灵活。
1.1.3 基于角色的访问控制:RBAC:Role Based Access Control
这是实际应用最多的一个模型。RBAC有几个概念:用户,会话,角色,权限。其中用户角色权限都好理解,而会话其实就是session,可以看做是登录验证通过后的句柄。
这个模型有4个变体:RBAC0,RBAC1,RBAC2,RBAC3,下面分别来看。
1.1.3.1 RBAC0
这是最简单的,一个用户只能对应多个角色,一个角色对应多个权限。如下图:
1.1.3.2 RBAC1
RBAC0有个麻烦的地方,当角色A有权限1到10共十个点,角色B有权限1到11共十一个点,你创建角色A之后,创建角色B的时候又为角色B再勾选十一个权限点。
RBAC1在RBAC0的基础上,引入了角色继承。上面的例子,你创建角色A之后,创建角色B时,只用继承角色A然后再另外勾选一个权限点就行了。
角色继承分为普通继承和受限继承。
普通继承,是指一个角色可以有多个父角色。利用普通继承,可以做到角色组的概念。
受限继承,是指一个角色只能有一个父角色。利用受限继承,可以做到角色的严格树形结构。
RBAC1如下图:
1.1.3.3 RBAC2
RBAC0还有个麻烦的地方,由于一个用户可以分配多个角色,如果把一个用户同时设置成裁判和球员,就糟糕了。
RBAC2在RBAC0的基础上,引入了责任分离。责任分离分为两种:静态责任分离SSD,动态责任分离DSD。
当给用户分配了球员角色时,就不允许再分配成裁判角色,这是静态责任分离的一种。
可以为用户同时分配球员和裁判角色,但是同一场比赛,用户只能使用一种身份参加,这是动态责任分离。
静态责任分离的本质是在分配角色时增加约束。约束有三种形式:角色互斥,就像上面的例子,不允许给用户同时分配球员和裁判;基数约束,限制一个用户能拥有的角色数量;先决条件约束,用户要拥有一个角色,必须先拥有另外一个角色,比如必须先成为工程师,才能成为架构师。
动态责任分离的本质是在系统运行时有所约束。比如用户既是球员也是裁判时,登录系统时必须选择其中一种角色登录,登录后只拥有被选角色的权限。
RBAC2如下图:
1.1.3.4 RBAC3
RBAC3就是同时实现RABC1和RBAC2,如下图:
1.1.4 基于属性的访问控制:ABAC:Attribute Based Access Control
ABAC的本质,是根据规则,动态计算一个或一组属性是否满足某种规则,来进行授权判断。通常用来计算的属性分为:用户属性,环境属性,操作属性和资源属性。可以用XML,YAML或其他形式来存储规则。
简单来说,就是把访问规则写在配置文件里,当用户要做操作的时候,规则引擎根据配置去计算结果。
ABAC的优点:
1. 规则集中式管理。也就是配置文件。
2. 可以按需实现不同颗粒的权限控制。意思是配置文件的规则,是自定义的,A模块可以做到菜单级,B模块可以做到功能级。
3. 不需要预定义判断逻辑,减轻了权限系统的维护成本,特别是在需求经常变化的系统中
缺点:
1. 不能直观地看出用户和权限之间的关系。
2. 规则如果复杂,或者设计混乱,会给管理者维护和追查带来麻烦。
3. 权限判断需要实时执行,规则过多会导致性能问题。
1.2 数据权限
数据权限,我觉得可以分为三个级别去讲:表级,行级,列级。
1.2.1 表级数据权限
作为一个技术员角色,就不应该看到销售数据,这就是表级权限,其实跟前面说的菜单权限是一个意思。
1.2.2 行级数据权限
作为基层销售,你只能看到自己的销售数据,作为销售总监,能看到销售部门所有人的数据,就是行级数据权限。从上面这个例子可以看出,行级数据权限是由组织结构决定的。当然最简单的办法就是硬编码,在组织结构里只能看自己和下级数据。优点是简单,缺点是不灵活,无法处理跨节点看数据的问题。
另一个办法就是配置用户和组织结构的关系,下图是一个例子:
1.2.2.1 把角色跟组织结构关联起来
像上图所示,把角色跟组织机构关联起来,也就间接把用户跟组织结构关联了,你就知道谁官大谁官小了,同一个数据表,村长能看自己村的,县长能看十几个村的。
1.2.2.2 把用户跟组织结构关联起来
也可以直接把用户跟组织机构关联起来,做起来简单,但是调整的时候偏麻烦一点。
1.2.2.3 通过岗位,把用户和组织结构关联起来
如果给角色分配组织结构,可能会造成角色承担过多责任。如果直接给用户分配组织结构,可能会造成调整麻烦。于是我们可以引入岗位的概念,通过岗位把用户和组织结构关联起来。
以上就是通过组织结构解决行级数据权限的方法。其背后还存在一个问题,一个用户可以同时站在组织结构的多个节点上吗?通俗的说就是,一个人可以同时是村长和县长吗?如果可以,他能看全县所有村的数据吗?
这个问题要看实际业务情况来定。如果不能兼任,就不存在这个问题了。如果允许兼任,数据权限就应该取并集。
1.2.3 列级数据权限
我们假设一个不太严谨的场景,销售数据包括销售员,客户信息,合同编号,金额,提成。销售总监,可以看到销售部门所有销售数据,但是提成这一列是看不到的。这个场景就是列级数据权限。
当然最简单,还是硬编码。写死某些角色就是看不到某列数据。同样,优点是简单,缺点是不灵活。
1.2.3.1 数据资源
引入一个概念,数据资源,说白了就是数据表,数据资源包含表里所有字段。接下来就跟行级权限处理一样了。