Function是绑定在ResourceType(class)上的,一种资源类型上有一个Function列表。record(object)从ResourceType(class)继承这些Function列表。这种绑定在对象上的函数叫Method,而绑定在ResourceType上的函数叫Operation,它们的名字不同只是因为所处的层次不同,ResourceType + Operation + Field是面向软件的最终用户的,而Class + Method + Property是面向开发人员的,核心区别仅此而已,别的区别都是细节。
把控“资源”和“功能”的正交关系
现在有这样一个问题:比如卧室里有“空调”、有“电风扇”,这两种资源都有“降温”的能力(功能)。
我想直接控制“降温”权限,而不是分别控制“使用空调降温”和“使用电风扇降温”怎么办呢?这里的“降温”可以认为是Function,而“使用空调降温”和“使用电风扇降温”可以认为是Operation,因为它们绑定到了资源上。“降温”能力集是比“使用空调降温”和“使用电风扇降温”能力集更大的能力集。
把函数固定在对象上,先定位对象然后再定位函数,将对象视为函数的耦合作用域(函数中传入的this对象)这是面向对象的方法论。把函数和对象分开然后通过(Function, Input, Output)组合成三元组这是函数式方法论。
在OO世界中,由于Function已经被绑定到Object和ObjectType上去了,所以当房间里有“空调”和“电风扇”这两种降温资源的时候我们若要控制某个主体不能降温的话就只有分别控制他不能“使用空调降温”和“使用电风扇降温”了。
试试通过变换资源树的结构能否解决上面那个问题呢?
+制冷设备
----电风扇(ResourceType)
--------电风扇降温(overwrite Operation)
--------风扇1(电风扇类型object1)
--------风扇2(电风扇类型object2)
----空调(ResourceType)
--------空调1(空调类型object1)
--------空调降温(overwrite Operation)
----降温(Operation)
现在,如果我们直接不让某个主体不能使用“制冷设备”下的“降温”功能的话是可以做到使他既不能“使用空调降温”也不能“使用电风扇降温”的。
但是,空调除了是“制冷设备”还是“制热设备”。重绘一下上图的树会是这样。
+制冷设备
----电风扇(ResourceType)
--------电风扇降温(overwrite Operation)
--------风扇1(电风扇类型object1)
--------风扇2(电风扇类型object2)
----空调(ResourceType)
--------空调1(空调类型object1)
--------空调降温(overwrite Operation)
----降温(Operation)
+制热设备
----空调(ResourceType)
--------空调1(空调类型object1)
--------空调制热(overwrite Operation)
----制热(Operation)
融合“面向对象式”和“函数式”
问题出来了:“空调”节点在资源树上出现在了两个位置。这违反了树形结构,违反了构造定理,所以我们错了。
我们得从资源树上“剪掉”制冷设备和制热设备这两个节点,得把它们放入新的维度中去。那个新的维度是什么?是函数维度。上面我们遇到的问题是因为我们钻到资源树这一棵树中去了,“制冷设备”“制热设备”中的“设备”是资源,而“制冷”和“制热”是函数。
从资源的角度永远没办法解决空调既出现在制冷设备节点下又出现在制热设备节点下这个问题。资源和功能组合起来后就很好的解决了。(使用空调制冷"Operation",制冷"Function")(使用空调制热"Operation",制热"Function")(使用电风扇制冷"Operation",制冷"Function")(使用电热扇制热"Operation",制热"Function")。
函数(能力、运动、时间)是适合组合到资源(空间)上的,只有与特定类型的资源十分紧密依赖的函数才是可以沿着资源树继承的。
在Anycmd这个开源权限引擎中断言过(Function, Function)这种类型的二元组是有意义的,现在终于几乎确定找到了它的意义。(使用空调制冷"Operation",制冷"Function")这个二元组就是(Function, Function)类型的二元组(Operation集是Function集的子集,Operation是特殊的Function)。
(Function, Function)类型的Privilege二元组
(Function, Function)这种二元组目的是建立Function之间的层次关系。
在appSystem节点上(appSystem节点是根,虽然在空调和电风扇共同的任意父节点上都行但最佳应在appSystem这个根节点上,根节点是Global对象)添加一条命名为“制冷”的Operation记录。然后建立(使用空调制冷"Operation",制冷"Function")(使用空调制热"Operation",制热"Function")(使用电风扇制冷"Operation",制冷"Function")这种(Function, Function)类型的二元组合。表示“电风扇制冷”和“空调制冷”继承“制冷”,从而安全引擎鉴权当前请求“空调制冷”的主体是否有权限的时候找到“空调制冷”这条Function记录的父级记录“制冷”,然后鉴权是沿着Function的层次进行一级一级向下进行的,如果当前主体没有“制冷”权限就直接没有权限了,如果有“制冷”权限再接着验证“空调制冷”权限。
需要提及的是:
制冷”这条function记录并不对应实际的程序员书写的功能代码,而只是一条记录,这条记录的目的只是为制冷这种功能取个名字生成一个标识,然后用来和业务系统中的绑定在资源上的那些“操作”(绑定在资源上的Function称Operation)建立(function, function)类型是组合从而表达功能间的层次关系。
权限引擎在智能家具领域的应用:
上面那种逻辑在智能家居中可以应用。1 比如家长担心使用电风扇制冷存在安全风险(担心小孩子会将线头布条输入旋转的电风扇中),所以家长主体可以将家居这个appSystem环境设置为当只有小孩子一个人在家的时候系统拒绝小孩主体打开电风扇,但允许小孩子打开空调;2 当家居中的主体数量大于3人时空调和电风扇可以被同时打开,当少于3人时只能打开其中之一。即使最终用户有任意复杂的授权和鉴权需求Anycmd开源权限引擎几乎都能满足。