标签:
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)这种二元组目的是建立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开源权限引擎几乎都能满足。
角色表示能力,得到某个角色的账户具有了这个角色表示的能力,但是能力是作用在资源上的,主体只得到了能力还没有用,还得有资源,有施展能力的资源能力才有用。比如我们把所有的角色都给某个账户,都给这个账户也是没有用的,如果不让这个账户能够操作任何资源记录的话它有再多的角色也没用。 角色表示的是个功能集,得到某个角色的账户就得到了这个角色代表的功能,只是表示它有干某些种类的事情的能力了,可是我们不让它看到任何资源的话它的能力就没有施展的目标。比如一个账户具有了修改产品的价格的权限,产品上会有个Catalog属性,这个Catalog属性的取值来自于一棵树上的节点,比如来自一棵ProductCatalog树,我们不给这个账户的Privilege二元组集合添加任何(Account, ProductCatalog)类型的记录的话,这个账户是看不到任何产品记录的。
Catalog模块是为了建立一片森林,每一个Catalog根节点都定性了一棵树,可以有ProductCatalog树、AccountCatalog树(也就是Organization,用户的组织结构),等各种各样的树,每棵树上取一个节点取若干棵树上的节点组成一个元组,这个元组可以标识出整个资源空间中的任何一个任何粒度的资源子集,然后我们把主体投放到具体的空间子集中去施展他/她的能力。 森林中的每一棵树上的节点所指代的都是整个资源集中的一个子集,我们通过这片森林可以把整个资源集划分成任意细致的子集。一直能划分到具体资源记录的具体单元格的具体值域的具体取值。 我们把这种由Catalog树划分的资源称作空间。使用这片森林来把整个资源空间集合划分成一个幂集。这样,由角色得到的功能集(能力集)和由Catalog得到的数据集是完全正交的,即使一个账户得到了所有的角色,但是如果没得到任何Catalog节点指代的资源的话也是啥了干不了的。 比如有5棵树组成的这片森林{tree1,tree2,tree3,tree4,tree5},我们从这5棵树上分别取一个节点组成这样一个5元组(tree1.Node001,tree2.Node01.02,tree3.01,tree4.10,tree5.node3)。这个5元组定位了资源空间中的一个子集,通过这样的5元组我们能够定位到整个资源空间的任意精细的子集,我们可以把给定的主体投放到那个空间中去,主体只有来到了具体的资源空间才能施展他的能力。即使一个主体拥有很多角色也没有用处的,因为他身上的那些能力只有在来到具体的空间中才会发挥作用的。试想一下一个会做饭的主体不在厨房没有油盐酱醋茶,一个会驾驶的主体没有车子 Catalog抽象了一切,Codespace、ResourceType、Field、值域、具体的值,都是Catalog森林上的节点。
普通的分类只是对一个集合中的所有元素进行简单的单元划分,分成几个兄弟组,这些兄弟组下面不再继续分类。复杂的分类是那个Catalog(目录)树,复杂的分类才是棵树。简单的分类直接使用Dic和DicItem模型去表达就可以。普通的分类其实就是实体的属性。实体上的CategoryCode字段与实体的固有属性没有本质差别,只是CategoryCode这样的字段是系统附加给实体的字段,而固有属性是业务附加给实体的字段。实体的一个固有属性的本质也是一次分类,比如人的性别属性,取值为男、女、未知、未说明的意思就是把人按照性别分为4类。人的姓名也是分类,只不过这种分类的枚举值比性别要多的多。人的年龄也是分类,年龄分类的取值也很多。对于取值非常多的那些分类项通常人们引入计算逻辑,合理分配存储和计算。
标签:
原文地址:http://www.cnblogs.com/acengine/p/4280273.html