续:关于权限系统的设计

Note:
首先,向版主致歉。这原是关于权限系统设计问题的回帖,本不应该另开新贴。而在下的另开新贴,一方面是因为本人的观点中与很多人的观点差别较大,另一方面也担心其会被“埋没”在原贴的大量回帖中。此外,本贴的内容整理与编排耗费了我周末接近一整个晚上的时间,包含了我对近期项目中权限系统的思考与总结,希望引来大家足够的目光和指导。请版主体谅。


权限系统,其重要性当然不言自明。看见大家的方案,有相当多优秀的创意与经验,我的项目也有所涉及,以下说明的是我最近在一个企业 EJB 项目中初步实现的方案(以及设计考量),望与诸位共商榷。


前言:

权限往往是一个极其复杂的问题,但也可简单表述为这样的逻辑表达式:判断“who 对 what(which) 进行 how 的操作”的逻辑表达式是否为真。

针对不同的应用,需要根据项目的实际情况和具体架构,在维护性、灵活性、完整性等N多个方案之间比较权衡,选择符合的方案。


目标:

这个权限系统的设计,我主要考虑了这么几个目标:

直观,因为系统最终会由最终用户来维护,权限分配的直观和容易理解,显得比较重要,系统不辞劳苦的实现了组的继承,除了功能的必须,更主要的就是因为它足够直观。

简单,包括概念数量上的简单和意义上的简单还有功能上的简单。想用一个权限系统解决所有的权限问题是不现实的。设计中将常常变化的“定制”特点比较强的部分判断为业务逻辑,而将常常相同的“通用”特点比较强的部分判断为权限逻辑就是基于这样的思路。此外,同时具备 Role 和 Group 的系统难于理解,权衡之下,摒弃了 Role 概念。

扩展,我在以前的项目中也实现过基于 Role 概念的权限系统,但效果不太理想。之所以在这里摒弃 Role 的概念,另一个原因就是因为它不易扩展。通常 Role 的设计方式意味着预先已经定好了一组权限,这样的“预先设计”,常常会鼓励程序员 hardcode 这些权限相关的部分,而,如果这么做的话,当需要重新定义 Role 时,扩展就会变得极为困难。而采用可继承的 Group 概念在支持权限以组方式定义的同时有效避免了重定义时在扩展上的困难。


名词:

下面两个名词极其重要,是整个设计问题边界定义的关键,或许我的理解与通常的理解不同,在此有必要特别澄清。

粗粒度:表示类别级,即,仅考虑对象的类别,不考虑对象的某个特定实例。比方,用户管理中,创建、删除,对所有的用户都一视同仁,并不区分操作的具体对象实例。

细粒度:表示实例级,即,需要考虑具体对象的实例,当然,细粒度是在考虑粗粒度的对象类别之后才再考虑特定实例。比方,合同管理中,列表、删除,需要区分该合同实例是否为当前用户所创建。


原则:

权限逻辑配合业务逻辑。即,权限系统以为业务逻辑提供服务为目标。纯粹纸面意义的极其复杂和精巧的权限系统,这里不作讨论。相当多细粒度的权限问题因其极其独特而不具通用意义,它们也能被理解为是“业务逻辑”的一部分。比方,要求:“合同资源只能被它的创建者删除,与创建者同组的用户可以修改,所有的用户能够浏览”。这既可以认为是一个细粒度的权限问题,也可以认为是一个业务逻辑问题。在这里我认为它是业务逻辑问题,在整个权限系统的架构设计之中不予过多考虑。当然,权限系统的架构也必须要能支持这样的控制判断。或者说,系统提供足够多但不是完全的控制能力。即,设计原则归结为:“系统只提供粗粒度的权限,细粒度的权限被认为是业务逻辑的职责”。

需要再次强调的是,这里表述的权限系统仅是一个“不完全”的权限系统,即,它不提供所有关于权限的问题的解决方法。它提供一个基础,并解决那些具有“共性”的(或者说粗粒度的)部分。在这个基础之上,根据“业务逻辑”的独特权限需求,编码实现剩余部分(或者说细粒度的)部分,才算完整。回到权限的问题公式,我的设计仅解决了 who + what + how 的问题,which 的权限问题留给业务逻辑解决。


概念:

User:用户。解决 who 的问题。

Group:组。权限分配的单位与载体。权限不考虑分配给特定的用户。组可以包括组(以实现权限的继承)。

Operate:操作。表明对 what 的 how 操作。


说明:

User

与大家的都一样,没什么好说的。

Group

与大家的类似,所不同的是,Group 要实现继承。即,在创建时必须要指定该 Group 的 Parent 是什么 Group 。在粗粒度控制上,可以认为,只要某用户直接或者间接的属于某个 Group 那么它就具备这个 Group 的所有操作许可。细粒度控制上,在业务逻辑的判断中,User 仅应关注其直接属于的 Group ,用来判断是否“同组”,间接的 Group 对权限的控制意义不大,试设想存在一个 All User 的 Group 是所有 Group 的祖先,这样的情形下,判断的结果不具备实际意义。

User 与 Group 是多对多的关系。即,一个 User 可以属于多个 Group 之中,一个 Group 可以包括多个 User 。

子 Group 与 父 Group 是多对一的关系。即,一个子 Group 只能有一个父 Group ,一个父 Group 可以包括多个子 Group 。


Operate

某种意义上类似于大家的 Resource + Privilege 概念,但,这里的 Resource 仅包括 Resource Type 不表示 Resource Instance。Operate 概念上与大家的观点区别比较,后面有详细的解释。

Group 与 Operate 是多对多的关系。

各概念的关系图示如下:


User
|*
|
|* 1
Group---+
|* |* |
| +---+
|*
Operate

解释:

Operate 的定义包括了 Resource Type 和 Method 概念。即, what 和 how 的概念。之所以将 what 和 how 绑定在一起作为一个 Operate 概念而不是分开建模再建立关联,这是因为很多的 how 对于某 what 才有意义。比方,发布操作对新闻对象才有意义,对用户对象则没有意义。

how 本身的意义也有所不同,这里并非仅定义类 UNIX 的 RWX 三种操作,这样的定义对于文件系统是合理的,但,对于其他的应用领域或许就不是那么足够了。具体来说,对于每一个 what 可以定义 N 种操作。比方,对于合同这类对象,可以定义创建操作、提交操作、检查冲突操作等。可以认为,how 概念对应于每一个商业方法。

其中,与具体用户身份相关的操作既可以定义在操作的业务逻辑之中,也可以定义在操作级别。比方,创建者的浏览视图与普通用户的浏览视图要求内容不同。你既可以在外部定义两个操作方法,也可以在一个操作方法的内部根据具体逻辑进行处理。具体应用哪一种方式应依据实际情况进行处理。

这样的架构,应能在易于理解和管理的情况下,满足绝大部分粗粒度权限控制的功能需要。但是,除了粗粒度权限,无可否认,系统中必然还会包括无数对具体 Instance 的细粒度权限。这些问题,被留给业务逻辑来解决,这样的考虑基于以下两点。

一方面,细粒度的权限判断必须要在资源上建模权限分配的支持信息才可能得以实现。比方,如果要求创建者和普通用户看到不同的信息内容,那么,资源本身应该有其创建者的信息。如同 Unix 的每一个文件(资源),都定义了对 Owner, Group, All 的不同操作属性。

另一方面,细粒度的权限常常具有相当大的业务逻辑相关性。对不同的业务逻辑,常常意味着完全不同的权限判定原则和策略。相比之下,粗粒度的权限更具通用性,将其实现为一个架构,更有重用价值;而将细粒度的权限判断实现为一个架构级别的东西就显得繁琐,而且不是那么的有必要,用定制的代码来实现就更简洁,更灵活。


结语:

希望我的文字表述清楚,也希望我的方案能激起大家讨论研究的兴趣。

欢迎讨论。

非常有分量的文章,文章从架构的高度将权限系统划分两大部分我认为是正确的。

但是舍弃role概念是否需要再进一步斟酌?

我个人认为,role可以是粗粒度和细粒度(业务逻辑)的接口,假设我们开发了一个基于粗粒度控制的权限框架软件,那么我们对外的接口是什么?我觉得应该是role, 具体业务实现可以直接继承或拓展丰富role的内容,后者属于细粒度。

role不是如同user或group的具体实体,他应该是接口概念,抽象的通称。

我的方法中与大家区别最大的部分可能就在于――在粗粒度的控制上“以 group 的继承取代 role 的组合”。

to: Banq,你说得有道理,但是请看我下面对于 cc 举例的分析。

to: cc,谢谢你的举例,非常直观。

我注意到你的举例与我以前实现的权限极其类似,它的关联是以一个“三元组合”的形式出现的 user-group-role ,即“谁在什么组充当什么角色”,也就是说,它实际上是以纯粹的组合方式定义权限的。基于组合的设计, Group 可以直接映射组织结构,Role 可以直接映射组织结构中的业务角色,比较直观,而且也足够灵活。

在这样的结构下,可以认为, Role 是一个非关键概念。试想,如果没有 role ,直接采用 user-group-permission 的关联也是可以实现组合的,只是对于一个用户来说,数据量可能会非常庞大。而 role 的引入实际上大大缓解了这种状况,也就是说一条记录意味着“给这个 group 的这个 user role 分配了定义的所有这些 permission ”,而不是每个 permission 一条记录,在这里,它仅仅意味着“一组权限”,它对系统的贡献实质上就是提供了一个比较粗颗粒的分配单位。在组合的方式下,这样的设计是合理的。


但是这一纯粹的组合方式存在这样的问题:

1. user-group-role 是一个扁平的关联关系,必须同时定义 user-group-role ,这个三元关系需要(而且必要)解构。比如,如何反应 user-group 之间的关系?ok,你可以定义 user-group 关系,那么,此时, user-group 与 user-group-role 两个关系之间是什么关系?ok,你还可以取消 user-group-role 再定义 group-role ,此时通过 group 作为中转就可以实现 user-group-role 了。问题是,在这样的定义下,role 的贡献――“定义一组 permission ”不再那么有意义,那么,为什么不去掉 role ,直接定义 group-permission 关系呢?

2. 注意,此时,user group permission 已经极其类似于我的 user group operate 方案了。

3. 比起权限的组合,继承似乎更容易理解。子组继承父组的所有权限,规则来得更简单,同时意味着管理更容易。如何更进一步实现权限的继承?最直接的就是在 group 上引入“父子关系”。OK,再看,这基本上就是我的 group 继承方案了。

4. 更进一步,关于 permission 的细化与改进。容后再谈。

今天太忙,到现在才有时间来谈“容后再谈”的 permission 的扩展。

假设我们开发了一个粗粒度的权限控制框架软件,现在将它作为一个组件提供给用户,需要提供对外的接口。那么,如何提供扩展能力?或者说,在上面讨论的这样一个比较粗糙的权限控制系统中,在哪一个概念上进行扩展会比较合适?


考虑一下“who + what(which) + how ”的概念公式,什么部分是会常常需要扩展的呢?可以用排除法,毫无疑问,有了用户/权限管理的基本框架,who(User/Group) 的概念是不会经常需要扩展的。变化的可能是系统中引入新的 what (新的 resource 类型)或者新的 how (新的操作方式)。那么,排除了 User 和 Group 之后,在三个基本概念中,仅在 permission 上进行扩展是否足够?我们可以先考虑这样的设计中 permission 实质上映射了应用中的什么概念?第一感觉是 permission 解决了 how 的问题,即,这个概念表示了“怎样”的操作。


那么,这个“怎样”是在哪一个层次上的定义呢?个人认为,将 permission 定义在“商业方法”级别可能会比较合适,注意,这里可能是我与大家方案区别巨大的另一个重点之所在。

比方,发布、购买、取消。每一个商业方法可以意味着用户进行的一个“动作”(用例?maybe)。这些操作更高级的概念可能是信息发布子系统,商品销售子系统,订单管理子系统,在这个级别上定义 permission 在某些情况下或许也是合理的,但显然不够灵活。

在更低的级别上,或许可以设想在某些表(或者信息字段)的 CRUQ (增删改查)动作上定义 permission 概念。再通过这些权限的组合与交叉,用更少的 permission 表述复杂的操作。这往往是很多程序员最直接的想法(也是我以前对于权限定义的想法)。初一看,似乎简单明了,而且好像能够简化维护工作。但,实际上,这样的定义方式不仅过于繁琐,仅就功能而言也是不足取的。

一方面,这样的定义方式不足够完成更复杂的权限辨别。比方,一个购买操作,就可能意味着对系统中 N 个表的检索,更新,乃至删除。在这样的情况下,对多个表的 permission 的组合将会极其令人痛苦,因为基本上,所有可能用到的操作都必须开放给每一个可能要进行这种操作的用户。

另一方面,这样的方式因为将权限深入到了系统的数据访问层,使用起来将极其不便。也就是说,在这样的定义模式下,每一个数据访问方法都必需要知道当前的操作者是谁――在数据访问逻辑中必需要知道用户身份,这不仅让人费解,而且让人沮丧(实在惭愧,这样的设计本人就做过)。

而,定义在商业逻辑的层次上,一方面保证了数据访问代码的“纯洁性”,另一方面在功能上也是“足够”的。也就是说,对更低层次,能自由的访问数据,对更高层次,也能比较精细的控制权限。


确定了 permission 定义的合适层次,更进一步,我们能够发现 permission 实际上还隐含了 what 的概念。也就是说,对于 what 的 how 操作才会是一个完整的 permission 。只要确定了 permission 的定义层次,这一点并不难了解。比方,“发布”操作,隐含了“信息”的“发布”概念,而对于“商品”而言发布操作是没有意义的。同样的,“购买”操作,隐含了“商品”的“购买”概念。这里的绑定还体现在大量通用的同名的操作上,比方,你需要区分“商品的删除”与“信息的删除”这两个同名为“删除”的不同操作。

注:我方案中将“ permission + resource ”合起来的概念称作一个“ Operate ”以示区别。更复杂的系统或许会需要一个“permission + resource 关联”方案的实现,但这样的实现应该说与两者合并的方案在大的概念上并无二致,其中的必要和实现,这里不做讨论。


回到我们的问题――如何提供权限系统的扩展能力?我的答案应该比较明确了,是在 Operate (Resource + Permission) 的概念上进行扩展。那么具体来说应该怎么样的模式来实现扩展呢?


或许如同 GoF 著名的 Design Pattern 中提到的 Proxy 模式会是一个非常棒的方式。我的实现大致是这样的:在商业方法层(EJB Session Facade [Stateful sessionbean]中),取得该商业方法的 methodname ,再根据 classname 和 methodname 检索 operate 数据,然后依据这个 operate 信息和 stateful 中保存的 user 信息判断当前用户是否具备该方法的操作权限。个人认为 Banq 提供的“基于动态 proxy 的权限实现方法”要更优雅一些。 :)

是不是这样的?


public class Message{
.............
public List void QueryByName(String name){
............
return ResultList;
}
}

public class MessageProxy extends Message{
private Message message;
private User user;
private Permission permission;
.............
public List QueryByName(String name){
if (permission.getPermission("类名","方法名",user)){
return message.QueryByName(String name);
}else{
return null;
}
}
}

的确啊,Role这个类看来似乎作用很小。其实,你把permission也role合在一起了。

exactly! 代码中看起来就是这样的。

实际上,以前 role 起到的“权限集合”作用被 group 从其父 group 继承的 permission 集合取代了。

因为 group 是可继承的,对于一个分级的权限实现,某个 group 通过“继承”就已经直接获得了其父 group 所拥有的所有“权限集合”,对这个 group 而言,需要与权限建立直接关联的,仅是它比起其父 group 需要“扩展”的那部分权限。可以预计,这些需要扩展的部分其数量是非常有限的。在这样的情况下,“权限集合”所能发挥的“降低冗余”的作用已经非常弱。所以,这样的结构下就已经不再迫切需要以提供“权限集合”为目的的 role 概念。

我觉得,Group就是Role,如果你把Group全部换个名称,就行了。

role直接有继承,就像经理继承了员工,经理就是员工嘛,经理是个role,员工是个role,多个user都扮演员工role,少数user扮演经理role 。

这么表述似乎也是合理的。

就是有点不习惯而已。呵呵……

看来我们的意思还是基本一致。

role在有些情况下没有必要出现,除非我们要专门开发一个权限系统的通用软件。role从概念上其实没有实在的东西,它可以被group+permission来替代。

呵呵,在来这里讨论以前,我总搞不清 Role 和 Group 有什么区别。
经过讨论以后,我觉得Role 是 privilege 的集合,Group 是 User 的集合,这个模型很好,结构很清析。

但是,看到你们的讨论,呵呵,这又使我想起了我自己的混乱日子。

我觉得,这些其实都是模型,在实际应用中是不是要这样实现又是另一回事。我这就有一个简单,而且正在使用的权限系统。
系统只有 Administrator 和 Manager 角色,因为用户的需求就只要这样的结构,Administrator 能看到所有的管理视图,Manager 只能看到赋了权限的管理视图。所以这个系统的权限模块很简单。

于是,我有时就在想,权限系统是如此的应用广泛,是不是应该做成通用的模块呢? 但是,想想实际应用,好像又比较难,因为需求差异很大。
可我在冥冥之中好像又看到了什么。呵呵,像在写小说了,算了,有空好好设计一下框架,相信应该可以有解决办法。

另外再说一点我的想法:

我从系统边界来看权限应用的问题。
也许可以帮助大家和我自己澄清一些东西。

首先,系统的边界由以下三部分构成:

1.创造权限
2.分配权限
3.使用权限

然后,系统各部分的主要参与者对照如下:
1.创造权限 - Programmer 创造
2.分配权限 - Administrator 分配
3.使用权限 - User 使用

从边界的角度来看问题,可以很清楚地看到,

1. Programer 向权限系统提供 Operator = Privilege + Resource
( 我把它叫做 PrivilegeInstance, jackyz 给起了个很好听的名字,
叫 Operator, 那我也借用一下,后面都叫做 Operator ).

2. Administrator 利用 Operator 这个基本元素,来创造他理想中的权限模型。
如,创建角色,创建用户组,给用户组分配用户,将用户组与角色关联等等...
这些操作都是由 Administrator 来完成的.

3. User 使用 Administrator 分配给的权限去使用各个系统。

所以,我认为,象上面我们讨论的很多 Role/Group 的问题,都可以由 Administrator 来考虑。
Administrator 是用户,我不认为用户会建很复杂和很繁锁的模型。在他的心目中应该会有一个
比较适合他管理和维护的权限模型。

于是,程序员只要回答一个问题,就是, 什么权限可以访问什么资源,也就是前面说的 Operator.
程序员提供 Operator 就意味着给系统穿上了盔甲。

Administrator 就可以按照他的意愿来建立他所希望的权限框架。
(如果将 Programer 看作是 Basic 的发明者, Administrator 就是 Basic 的使用者,他可以做一些脚本式的编程)

** 我一直都在强调 Operator 的重要性,因为,这是这个系统中最关键的部分,它是一个纽带!
一个系在 Programer, Administrator, User 之间的纽带。

综上所述,我觉得应该向用户(指 Administrator)建议一个模型,但是也允许用户使用自己喜欢的模型。

TO:CC,Jackyz

我以前也想过将授权控制在每一个具体类的方法上。
但是,当我跳出来,想一想,用户的操作都是通过 GUI 来操作的
(即使是 Command line 方式,我也称其为 GUI)
于是,在受控视图上做授权处理不是更符合思维逻辑?
看起来也更优雅吗?

to: iceant, 谢谢你富有建设性的意见。

我们彼此方案之间的差异或许并不像它们看起来的那么巨大。

权限问题最终是为了解决一个“ who + what(which) + how ”的逻辑问题,在大家目前取得的概念共识之上,也可以归结为“ User 与 Privilege 的对应关系”问题。功能上,一个权限系统只要它能回答“某 User 是否有某 Privilege ”这个问题,那它就是可用的,在这个意义上,采用 Group 也好 Role 也好,尽可以归结为“具体实现”的范畴。然而,引入一个概念就必须要负责维护它。从维护的角度,如何尽可能的“keep it simply”,也是值得花费精力去考虑的一个问题。

“Role 是 Privilege 的集合,Group 是 User 的集合”,这已是我们大家都能认同的观点,只是,我认为在特定架构之下,具体来说就是在“Group 继承父 Group 的 Privilege”方案下, Role 的“Privilege 集合功能”已能通过“Group 关联 Privilege”以及“Group 继承”得以有效替代,从而退化成一个非关键概念,此时就可以在不影响功能的前提下合理“减免”这个概念。它不是一种“革新”,充其量只能算是一点“改进”。

你提出的从系统边界来看权限应用问题的观点我很赞同。我认为,如果能够满足你提到的这三个方面的需求,那么,架构出一个“比较通用”的权限系统是完全有可能的。
1.创造权限,由 Programer 来创造权限(定义 Operate)。并将定义好的权限存到数据库中以利分配。
2.分配权限,由 Administrator 根据自己的权限策略来规划和分配定义好的权限。个人认为,从数据库取得就可以了,让 Administrator 编程?似乎比较难。
3.使用权限,可以分为两个部分,其一,查询权限;即,解决“根据该用户的权限,他能进行一些什么操作”的问题,以满足表示层的需要。其二,执行权限,即,解决“他执行某个操作,是否符合该用户的权限”,以供业务层的使用。
提供给 Administrator 的部分应是相对稳定的。而我们所说的扩展,主要应是第1,3概念上的扩展,也就是说,可扩展性是对 Programer 而言的,具体来说,也就归结为“系统如何更方便的为 Programer 提供定义与使用权限的能力”。

你提在视图中控制权限,我认为在某些情况下也是可行的。当然,这个问题应与具体的应用模型相关。我的应用在 EJB 模式下,可以定义一个很明确的 Bussiness 层次,而一个 Bussiness 可能意味着不同的视图,当多个视图都对应于一个业务逻辑的时候,比如, Swing Client 以及 Jsp Client 访问的是同一个 EJB 实现的 Bussiness。在 Bussiness 层上应用权限较能提供集中的控制能力。实际上,如同我上面提到的,如果权限系统提供了查询能力,那么你会发现,在视图层次已经可以不去理解权限,它只需要根据查询结果控制界面就可以了。

再次回溯到上个问题“系统如何更方便的为 Programer 提供定义与使用权限的能力?”。那么,我们的系统在哪些部分是最为“活跃”的呢?或者说,对于一个通用的权限系统而言,我们每次在一个新的项目中重用它,哪些部分的工作量最大?当然,表示层已经面目全非,然而,引起这个变化是因为你的业务已经完全不同,也就是说,业务层的具体类往往是要根据项目需求重新设计的。在这个命题下,将权限控制在“业务层具体类的方法”上,也不失为一个简洁的重用方案。

"关于权限控制的讨论"让我受益不少,感谢参与讨论的各位朋友!希望就这个话题进行更深入的讨论!
到目前为止,我们讨论的"权限控制",实际上是默认了这样的前提:所有的user地位平等,由权限控制元数据决定他的权限。
但在很多系统中,user的地位不是平等的。user本身是庞大行政树中的一个节点。描述如下:
1.假设一个公司由若干个营业部组成,每个营业部又由若干个营业分部组成;从而在在行政级别上,组成了以总部为root的一棵树。
2.每个营业部有自己的account数据,收费标准,and so on;
3.每个user(或称为柜员)属于且只属于一个营业部;
4.每个user只能操作属于本营业部或本营业部下属机构(如:子营业部)的数据。
如上的描述是一个真实项目的权限控制要求,同时也应该是一个具有普遍性的模型。希望和大家展开讨论!

第一个问题是:关系型数据库怎么存储树型结构?
如jive保存message那样,虽然是用关系型数据库存储了树型结构,但我觉得那是一个很牵强的方法:数据完整性是通过程序来保证的,在数据库一级无法保证数据完整性。

谢谢!

to: blues 欢迎你的讨论

你的问题是否可以这么理解:
1.你担心上诉的设计无法满足“User 地位不平等”的状况。
2.你担心用关系型数据库存储了树型结构“数据完整性”无法得到保证。

如果上诉理解没有错误,那么我试图根据以上理解来回答你的问题。其中很多技术我也没有亲手实践,谬误之处请各位指出。

先试图回答你的第二个问题,在你的提问中,有一个名词呼之欲出,那就是 LDAP ,或者你被人建议――这样的树型结构用 LDAP 来存储更为合理。我没有实践过 LDAP ,与用关系型数据库的方案无从对比。但我觉得“用关系型数据库存储树型结构,数据完整性无法得到保证”这个假设是值得商榷的。

对于“数据完整性”,我理解是你可能会担心在 DB 中可能出现父子关系上的“指向断开”或者“循环指向”的情况。不能完全排除数据库系统级的错误偶尔会导致这种情况发生的可能性,但在业务方法上是能够改善的。

其一、合理运用外键,能有效保证数据的完整性,比如下面的DDL语句。

CREATE TABLE Group_Tab
(
Group_ID NUMBER(10) NOT NULL,
Group_PID NUMBER(10),
Group_Name VARCHAR2(32) NOT NULL UNIQUE,
Group_Note VARCHAR2(1000),
CONSTRAINT PK_Group_Tab PRIMARY KEY (Group_ID)
);

ALTER TABLE Group_Tab ADD CONSTRAINT Group_PID FOREIGN KEY (
Group_PID
)
REFERENCES Group_Tab (
Group_ID
);

其二、合理设计业务方法,能有效保证数据的完整性。比如,对于 Group 其 parentGroup 只能在 create 方法中指定,不提供修改它的业务方法。如果需要改变 parentGroup 属性,那么就 remove 再重新 create 。这样能够避免误操作引入“断链”或者“循环”。

或许你对数据完整性有另外的理解,那又另当别论了。


再看你的第一个问题。

个人认为,这里的“平等”是一个抽象概念上的问题,也就是说它们是同一个“类型”,比方说,总部的用户和分部的用户都是用户,就“用户”这个概念上来说这两个“实例”是“平等”的(相同类型的)。其权限是否“平等”,完全由其他关系的设定来决定的。也就是说,用户仅仅是纯粹的用户,权限是被分离出去了的。

具体的,结合你的应用,在上面讨论的系统中可以按照这样的策略来进行权限分配及业务逻辑设计。

创建一个这样的 Group 结构:

All Users
Staff
DepartA
DepartA Administrator
DepartB
DepartB Administrator
Partner
Supply
Sell
...

(这里用缩进代表父子关系,希望你能看懂)

这仅仅是一个粗粒度的控制框架,还不能完全满足你的业务需要。这样的定义,仅仅控制到用户能进行什么操作,没有控制到用户能对那些数据进行这些操作。这些部分与你的业务密切相关,需要你在业务建模以及逻辑编码中自己予以实现。

比如,你可能会需要实施类似这样的权限逻辑判断规则:
1.如果当前用户不具备该操作的权限那么掷出权限异常。(粗粒度,由权限系统提供的简单支持机制来扩展)
2.如果当前用户不在当前业务数据所定义的管理组中而且也不与业务数据的Owner同组那么掷出权限异常。(细粒度,需要在权限系统的支持信息之上自己定义逻辑和实现代码)

应该看到,类似的逻辑规则的实现,有赖与你对于业务部分的建模以及编码支持。它们是“高度定制”的,而不是“权限框架”中可以“通用”的部分。在权限系统中,它们是多变的,定制的,需要由程序定制和扩展的部分。

不知这样的回答是否对你有所启发?