2010-04-14 120 views
2

我们目前工作的一个项目,其中主要的域对象是内容节点,我们使用的是ACL-like系统,其中层次结构中的每个节点都可以包含覆盖或补充那些对父母的规则。例如,一切都基于角色和行为。策略快速遍历ACL

Node 1 - {Deny All, Allow Role1 View} 
\- Node 2 - {Allow Role2 View} 
    \- Node 3 - {Deny Role1 View} 

在这种情况下,规则将从上到下依次读取,因此节点3只能由Role2查看。这个概念并不复杂。

检索单个节点的规则可能会导致一些查询,获取所有父级,然后重新创建规则列表并对其进行评估,但是此过程可能非常麻烦,因为层次结构可能会变得非常深,并且可能会有一个每个节点上都有很多规则。

我一直在思考与准备每当权限更改并将其传播到一个更新的所有叶子节点可能被重新创建每个节点预先计算规则的表。

你认为任何其他战略,加快规则的检索和计算的?理想情况下,它应该在单个查询中完成,但树并不是最好的结构。

回答

3

我认为一个Observer Pattern可能会进行调整。

这个想法是,每个Node维护一个预先计算的列表,并且只是通知其父任何更新,以便它可以重新计算这个列表。

这可以通过两种不同的方式来完成:

  1. 通知发生了变化,但在每次更新

我会建议与1会不会重新计算任何

  • 重新计算如果可能的话,因为它不涉及重新计算整个世界时,根被更新,仅在需要时重新计算(其实是懒惰EVAL),但如果你更新很少,但需要极快的检索你可能更喜欢第二个选项(有更多的人赞成rency问题虽然)。

    让我们来说明解决方案1:

    Root ___ Node1 ___ Node1A 
        \   \__ Node1B 
         \_ Node2 ___ Node2A 
           \__ Node2B 
    

    现在,首先,它们都没有预先计算任何东西(有全在一个肮脏的状态),如果我问Node2A规则:

    • Node2A意识到这是脏的:它查询Node2规则
    • Node2意识到这是脏的:它查询Root
    • Root没有任何父,因此它不能被弄脏时,它发送其规则Node2
    • Node2高速缓存中的答案从Root,合并其与那些从Root接收的规则和清洁脏位,它把结果发送合并(现缓存),以Node2A
    • Node2A缓存,合并,清除脏位,并返回结果

    如果我随后询问Node2B规则:

    • Node2B脏,它查询Node2
    • Node2是干净的,它回复
    • Node2B缓存,合并,清洗脏位,并返回结果

    注意Node2没有重新计算任何东西。

    在更新情况:

    • 我更新Node1:我用的是Root缓存规则重新计算新规则,并发送一个节拍Node1ANode1B通知他们自己的缓存是过时的
    • Node1ANode1B设置他们的脏位,他们也会传播这个通知他们有小孩

    请注意,因为我缓存了Root规则,所以我不必查询Root对象,如果它足够简单的操作,则可能不希望完全缓存它们:如果您不在此处播放,并且查询Root只涉及一次往返记忆,你可能不想复制它以节省一些记忆和记录。

    希望它能让你走。

  • +0

    非常有帮助的回应,我想你是隐含地说:预先计算所有(在一个或多或少复杂的策略)。 – 2010-04-14 16:00:16

    +0

    一点都不浪费,这很浪费。我的意思是懒惰地计算(根据需要计算并缓存结果)并使用观察者模式来知道何时不推荐使用缓存的结果。 – 2010-04-14 17:09:00

    1

    您的预计算版本似乎存储与每个节点上的每个角色相关的所有权限。您可以通过遍历树来节省一点时间和空间,在到达它们时对节点编号,并为每个角色生成一个节点编号和权限更改的阵列,仅用于与该角色相关的权限更改的节点。这会在输入树的大小(包括其注释)中产生只有线性的输出。然后,当您检查节点角色权限时,请使用该节点的编号来搜索阵列,以便在巡视期间访问该节点时查找代表最近更改权限的阵列中的点。

    这可能会以某种方式与http://en.wikipedia.org/wiki/Range_Minimum_Queryhttp://en.wikipedia.org/wiki/Lowest_common_ancestor相关联,但我真的不知道这些引用是否有帮助。