XCommunity权限控制和配置体系
2009-06-28 19:46 Ivony... 阅读(762) 评论(0) 编辑 收藏 举报1、问题
我们知到一般说到权限管理配置,最常见的就是这样的形式:
in:某人、某事
out:允许或拒绝。
更强大一些无非加入用户组的概念,某用户组的人,某事。
但实际上,在稍微复杂的系统中,这样的模式是很糟糕的,比如说论坛。
比如说,我要定义一个这样的权限:
用户可以在自己发起的话题中修改自己发布的回复。
这里的某人是针对任何人的,而某事是:“在自己发起的话题中修改自己发布的回复”,最后控制级别是允许。
这里面有两个问题:
1、某人和某事是紧密联系在一起的,某事是针对特定的人的。而在传统的模式中,这两者是分开的,操作发起方应告诉权限控制系统完整的某事,即操作方还必须去判断这个是不是自己的话题和回复。
2、这个某事可以由几个基本条件组合出非常多的变化,不可能一开始都想到。
为了便于理解,我还是啰嗦两句,说明传统的方式会遇到多大的麻烦:
因为传统的权限控制方式只是简单的接受两个参数(某人,某事)然后查权限控制表,组合一下权限控制级别(Deny > Allow),然后告诉我们,你可不可以这么做。
那么,当用户点击修改按钮的时候,这个按钮必须自己判断出来,这个用户是不是在修改自己发表的回复,以及是不是在自己发起的话题里,然后告诉权限控制系统,这个用户正“在自己发起的话题中修改自己发布的回复”或者正“在不是自己发起的话题中修改自己发布的回复”或者。。。。。。
这样的组合我们不知道有多少种。
然后权限控制系统根据如此这些信息,查表得出结论,可以这么做。
所以,这种权限管理方式是不现实的。
2、权限项(ControlItem)
XCommunity的权限配置体系最小的配置项是权限控制项(ControlItem)。其定义为:
2{
3
4 bool IsSatisfied( IPrincipal user, string verb, params object[] frameObjects );
5
6 EntryControlType ControlType { get; }
7
8 string Name { get; }
9
10}
11
一个权限控制项就如同刚才我描述权限的那一个陈述句一样:“用户可以在自己发起的话题中修改自己发布的回复”。
将这个陈述句拆分成两个部分:“用户在自己发起的话题中修改自己发布的回复”,“可以”。
即条件(Condition)和控制类别(允许或拒绝)。
IsSatisfied方法用于判断当前是不是“用户在自己发起的话题中修改自己发布的回复”。
ControlType属性则告诉权限管理系统,如果是,则“可以”。
IsSatisfied方法的参数用于描述当前的情况(instance),使用了一个主谓宾结构来描述:
user,发起者,主语
verb,动词,谓语
frameObjects,所涉及到的框架对象,宾语。
这个结构中的核心是verb,动词。动词决定了宾语的结构,XCommunity预定义的动词与宾语结构的关系如下:
verb | 动词描述 | BoardFrame | TopicFrame | PostFrame | PublishedDocument |
ModifyPost | 修改一个帖子 | 帖子所属的话题 | 被修改的帖子 | ||
DeletePost | 从话题删除一个帖子 | 帖子所属的话题 | 被删除的帖子 | ||
ModifyTopicTitle | 修改话题的标题 | 话题所在的版面 | 被修改的话题 | ||
DeleteTopic | 从版面删除一个话题 | 话题所在的版面 | 被修改的话题 | ||
LaunchTopic | 在版面发起一个话题 | 发起话题的版面 | 用于发起话题的文档 | ||
AttachTopic | 加入一个话题的讨论 | 被参与的话题 | 用于发表回复的文档 |
BoardFrame、TopicFrame、PostFrame、PublishedDocument统称为框架对象(FrameObject)。frameObjects参数包含了所有相关的框架对象,由于在每一种宾语结构中,每个类型的对象都只有一个,所以用OfType方法来找出需要的框架对象。
用于描述“用户可以在自己发起的话题中修改自己发布的回复”的权限控制项的实现就可以是这样的:
2{
3 public bool IsSatisfied( IPrincipal user, string verb, params object[] frameObjects )
4 {
5 if ( verb != "ModifyPost" )
6 return false;
7
8 var topic = frameObjects.OfType<ITopicFrame>().Single();
9 if ( !user.Identity.IsMySelf( topic.Meta.Launcher ) )
10 return false;
11
12 var post = frameObjects.OfType<IPostFrame>().Single();
13 if ( post.IsTheme )
14 return false;
15
16 if ( !user.Identity.IsMySelf( post.Author ) )
17 return false;
18
19 return true;
20
21 }
22
23 public EntryControlType ControlType
24 {
25 get { return EntryControlType.Allow; }
26 }
27
28 public string Name
29 {
30 get { return "AllowModifyOwnResponseInOwnTopic"; }
31 }
32}
33
34
这样,所有已想到和没想到的权限设置都可以用一个个的类型来描述了。
3、配置
但是如果所有的权限控制项都用代码来实现,是不现实的。所以,同样的,权限控制项可以通过XML文件来配置。
一个权限控制项典型的配置如下:
<control-item>
<condition verb=”DeletePost” />
<control-type>Deny</control-type>
</control-item>
其中condition元素对应为IsSatisfied方法,control-type则对应ControlType属性。该控制项表示任何情况下都禁止删除帖子的操作。
<condition>元素主要有两种配置方案:
设置一个类或者方法来处理,如:
或
<condition method=”XCommunity.Forums.Users.ControlConditions.IsModifyOwnResponse” />
直接通过XML来配置一系列条件的组合,如上例的“用户可以在自己发起的话题中修改自己发布的回复”可以如此设置:
<condition verb=”ModifyPost” >
<topic launcher=”#current-logged” >
<post theme=”false” author=”#current-logged” >
</condition>
<control-type>Allow</control-type>
<control-item>
其中的topic和post会自动对应为frameObjects中的ITopicFrame对象和IPostFrame对象。当然,如果要对自定义类型的对象进行条件判断,也可以透过简单的语法实现:
<frame-object type=”MyTopic” >
<property name=”locked” value=”false” />
</frameObject>
</condition>
condition元素可以包含多个条件,各个条件之间都是与的关系,如果某个条件因为某些原因无法判断,例如找不到指定类型的对象,则直接判否。
4、控制组
权限控制项的粒度是很小的,很多时候我们需要设置一批权限控制项,所以我们需要将一些权限控制项组合在一起加以管理,这就是权限控制组,同样用XML文件来配置:
<control-item>
<condition verb=”ModifyPost” >
<topic launcher=”#current-logged” >
<post theme=”false” author=”#current-logged” >
</condition>
<control-type>Allow</control-type>
<control-item>
<control-item>
<condition verb=”AttachTopic”>
<frame-object type=”MyTopic”>
<property name=”locked” value=”false” />
</frameObject>
</condition>
</control-item>
</control-group>
但有时候同一个权限项可能被多个组包含,为了避免重复代码,所以还支持这样的语法。
<condition verb=”ModifyPost” >
<topic launcher=”#current-logged” >
<post theme=”false” author=”#current-logged” >
</condition>
<control-type>Allow</control-type>
<control-item>
<control-group>
<control-item ref=”AllowModifyOwnResponseInOwnTopic” />
</control-group>
同样的,控制组也可以命名,并且被包含于其他控制组内。
权限控制组和控制项的定义都必须包含在授权配置元素(authorities)内。不包含在任何权限控制组内的权限控制项和组定义必须是命名的(name属性是必须的),而在控制组内的内联定义则不能命名(不能有name属性),即authorities的直接子元素的control-item和control-group是必须具备name属性的,而control-group内的control-item和control-group则是不能有name属性的。