之前写过几个系统,但是对权限控制这一块都不是非常满意
落后与先进的权限控制
传统权限控制的缺点
1、传统而落后的权限控制是通过硬编码,为每个角色能做的事情进行编码,当某个角色的权限发生变化,或者有新的角色加入的时候,程序员就不得不加入新的代码。
比如一开始只有3个角色,超级管理员、管理员、老板。
如果是超级管理员:
逻辑1
如果是管理员 :
逻辑2
如果是老板:
逻辑3
因为业务发展,公司多了一个角色:行政,为了对行政进行权限控制,代码变成这样:
如果是超级管理员:
逻辑1
如果是管理员 :
逻辑2
如果是老板:
逻辑3
如果是行政:
逻辑4
在当前市场变化如此快速的情况下,这显然不可以接受,我们不能天天加班。
2、无法做到主体分层
在传统的权限控制模型中,因为是收到编码的限制,我们不可以做到无限极分层:
如果是超级管理员:
如果是销售部的超级管理员:
如果是外出组的超级管理员:
。。。
如果是电话组的外出管理员:
。。。
如果是网络部的超级管理员:
如果是管理员:
这的多恐怖!!
RBAC
RBAC全程是Role-Based Access Control ,基于角色的访问权限控制,就是对所有的资源,进行访问权限。
世界的活动抽象
所有的动作,我们都可以抽象为这样:
老王 吃 苹果
老王 杀 鱼
老王 查看 账本
老王 添加 新的账本
老王 查看 后台右边的菜单
老王 打 自己
学生 读 书
中国人 过 春节
...
我们可以看到,所有的炒作都是由三个部分组成:主体、动作、客体。或许你会想,“我在吃饭”怎么解释,不需要解释,因为这不是行为动作,而是状态,因此不需要发访问控制。
没有银弹
想写一个通用的权限控制?可以同时控制各种行为动作?
XXX可以发射导弹
XXX可以持枪
XXX可以升国旗
XXX可以敲代码
。。。
没有,因为每个业务不一样,我们需要在正确的时间做正确的事情。
我们不可以去检查每个人,看他们有没有持枪证
我们应该坐的是,当有人要去取枪的时候,查看他有没有持枪证
我们不可以检查每个人,看他有没有发射导弹的权利
我们应该在他进入导弹发射室的时候,检查他是否有发射导弹的权利
因此,我们不可能写一个程序,去实现所有的访问控制,因为当时大家都没有带上他的权限证明,正如你作为导弹发射师,不带证件去看演唱会一样
我们不能再你看演唱会的时候,去检查你是否有发射导弹的许可。
一个人有太多的权利,如果都带上,是不是太沉重?
吃饭的权利、睡觉的权利、XX的权利
那么,正确的方式应该是怎样的呢?
角色等级和权限
现实中,角色是有等级的。
所以访问控制一定要能做到角色是可以分级的。
所以,这是一颗角色树
用户划分
物以类聚,人以群分。如果人很多,我们一一给他们加角色很麻烦,所以我们会对他们进行分组。
以年龄划分:
婴儿
小孩
青少年
青年
壮年
中老年
老年
以财富划分:
超级富豪
富豪
财政自由者
贫民
然后,以后我们给这些人授权的时候,就可以按照分类来了,而不必为每个人直接授权。
或许你会说,为什么不建立上面的用户组也可以用角色的形式存在啊?
是的,可以,这只是划分手法的不同而已:
只是只是如果这样做了,那么当每一个角色出来,我们都要直接授权给需要授权的每个人,这是很麻烦的,为了简单化,我们需要对用户进行划分,就像一棵树,就是用户组树,结果和角色树一样。
数据流
从上图我们可以清楚看到,从用户到权限节点表都是稳定的,我们根据用户id,拿到用户具有的所有用户组、角色,并且最终拿到用户具有的所有权限节点。
但是还没完,我们必须根据具体的业务,在具体业务的关联表中传入节点id,从而得到最终资源表中哪些记录是我们拥有操作权限的。
例如:
如果要看是否有删除文件的权限,我们必须要查看权限文件表,用过权限id(n_id)找到文件ID(f_id),再根据f_id就可以确定文件表中,哪些文件可以被我们删除,而哪些不可以,当用户尝试删除那些不可以的文件的时候,就会被禁止。
权限粒度
一般来说,不同的权限划分粒度需要的表不一样
资源级权限控制
资源表
权限资源删除表 #确定角色/用户可以删除那些资源
权限转查看表 #确定角色/用户可以查看那些资源
权限资源编辑表 #确定角色/用户可以更新那些资源
权限资源添加表 #确定哪些角色/用户可以添加资源
这个粒度可以确定,哪些角色/用户可以删除、查看、编辑哪些资源!
资源操作级权限控制
如果不需要这么细的粒度,2张表就够了
资源表
权限资源表 #确定哪些角色/用户 可以操作该资源,包括增删改查等任何操作
我们可以看到, 将个资源授权给老板这个角色时,实际上授予了增删改查四个权利。
这种粒度不建议使用,太粗了。