sorry 上述 group 结构的格式信息丢失,应该是这样的:


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

我想提出一个疑问。
权限系统的模式是不是属于树结构????

以上的讨论似乎都是很理想化的一种讨论,比如说在实际项目中,一个系统可能会有几十个部门,而这几十个部门的功能又是重复的。比如说:A部门可以填报新闻, 而A部门可以查阅全部的新闻。B部门可以填报新闻,而B部门可以删除所有的新闻。而这几十个部门均可以修改自己部门的新闻。

如果按照模式来,我是不是应该建立以下功能,如:A部门新闻修改、B部门新闻修改、C部门新闻修改.........WW部门新闻修改。这样子是不是重复工作量很大???然后再将这些功能--》Role--》Group--》User。

有没有一个比较好的解决方法,将这种问题彻底解决。

不知是否正确理解了你的意图,姑妄答之。

你的担心似乎正是一个标准的“细粒度”控制场景。关于新闻修改,你可以只建立一个功能,在该功能中根据自己的业务进行“细粒度”的权限控制。比如你的用户权限分配是这样的:


AllUsers
Staff
Editor {superEditor}
FinanceChannel {user1, user2}
ITChannel {user3}
EduChannel {user4}
Tech
Marketing
HumanResource
Partner
Supply
Resale
...

你的新闻信息至少应该包含一个 owner 属性以支持你权限判断的功能需求。然后,你可以在 modifyNews 业务方法的 proxy 中如此检查:


public void modifyNews(News news) throws AuthrizeException {
if(! who.hasOperate("News","Modify") ) throw new AuthrizeException("Operate was not allowed!");
// 粗粒度的判断用户是否具有 news 的 modify 权限
User owner = news.getOwner();
// 取得 news 的 owner
Group[] ownerGroups = owner.getGroups();
// 取得 owner 所在的“直接组”(仅包括直接相关的组)
Group[] whoGroups = who.getGroupsWithInheritTree();
// 取得 who 的“所有相关组”(包括直接相关的组及其所有子组)
if(! containsGroup(whoGroups, ownerGroup) ) throw new AuthrizeException("Operate was not allowed!");
// 细粒度的判断 owner 用户所在的“直接组”是否被包含在 who 的“所有相关组”中
real.modifyNews(news);
// 执行 modify 操作
}

如此:

news1 的 owner 是 user1 那么 ownerGroups = { FinanceChannel }

当 who == user1 时 whoGroups = { FinanceChannel } 则 groupContains(whoGroups, ownerGroups) == true

当 who == user2 时 whoGroups = { FinanceChannel } 则 groupContains(whoGroups, ownerGroups) == true

当 who == user3 时 whoGroups = { ITChannel } 则 groupContains(whoGroups, ownerGroups) == false

当 who == user4 时 whoGroups = { EduChannel } 则 groupContains(whoGroups, ownerGroups) == false

当 who == superEditor 时 whoGroups = { Editor, FinanceChannel, ITChannel, EduChannel } 则 groupContains(whoGroups, ownerGroups) == true


这个逻辑,未知当否?

看了诸位的讨论受益匪浅,不知道是否有类似的Open Source可以参考?

通过搜索权限管理来到贵论坛,就看到这么精彩的讨论,实在是收益非浅。多谢各位了!
目前我也在做这个方面的设计。在实际设计中,有这种情况,部门会根据所接受的项目来动态的组建一些项目小组,不同的项目小组间的数据是不可见的,项目小组中也有各种角色,如项目经理、普通小组成员等等。这种情况更加依赖于动态项目和扩展需要而生成,具有极大的时效性。
请问该如何设计模型?

to: ryo

有类似的 OpenSource 系统,名为 Power2Acl ,应该能够满足大多数情况的功能需求。我的方案与 Power2Acl 最大的区别在于:我取消了用以实现“权限集合”功能的 Role 概念,取消的原因说明可以参考本贴的第二个跟帖《role的必要性》。

需要说明的是,我的方案不一定是完善的,或许有的地方我没有考虑到也说不定,作为一个 OpenSource 的项目,我想 Power2Acl 的设计或许也是有理由的,请根据自己项目的实际情况斟酌、判断。


to: raistlin

你提的问题非常好,那是一种很典型的权限管理应用场景。以我们目前讨论的权限架构,可以考虑这样的粗框架实现:

思路:针对不同的“角色”动态的建立不同的组(注:我的设计中没有角色,只有组),类似于这样:


...
Tech.Dept. {DeptM}
ProjectA {PMA}
Programer {PA, PB}
Designer {DA, DB}
Tester {TA, TB}
ProjectB
...

每个项目建立一个单独的 Group ,对于新的项目,建立新的 Group 即可。

细粒度控制方面:你的业务规则我不清楚,无从置喙。但在权限判断部分,应在商业方法上予以控制。比如:不同用户的“操作能力”是不同的(粗粒度的控制应能满足要求),不同用户的“可视区域”是不同的(体现在对被操作的对象的权限数据,是否允许当前用户访问,这需要你对业务数据建模的时候考虑权限控制需要)。

未知,如此作答是否满意。

jackyz大侠,你说得Power2Acl,我用google都搜不到,能否告知网址?
谢谢!

我尝试了一下jackyz大虾的设计思路,还有些问题没有弄明白,特在这里请教.

1.数据库中实现树型结构除了jackyz提出的方法以外,我还知道一种是利用编码来实现,例如:
每三位(可自定义)代表一层,


100 china
100-101 beijing
100-102 shanghai
100-101-001 chaoyan district(beijing)
.....

我个人认为这种方法比起前面的方法是否会好一些,不需要自连接只需要分析自己的编码就可以知道叶子节点的所有父节点了.

2.我个人觉得如果只是用GROUP(jackyz定义),是否具有很大的通用性呢?因为在企业中存在的组织结构更象是user的集合,意味着在软件中我们得花费精力和代码去维护这种组织结构.采用user-group-role得结构,就可以把group单独拿出来处理.但是如果采用得是jackyz的group,我不知道如何去建立并维护企业中的组织结构,因为这个group包涵了group和role,如果在此基础上去做,你会在区别group和role上费很多心思.

请指教

对于树型编码的数据库保存。
A是相当于保存一条父亲节点的信息。
B是相当于保存所有父节点的信息。

对于A来说,如果要进行一个节点的父节点的遍历的话,需要进行N次搜索,但在对父节点进行改动(比如删除等)操作时,比B来得方便,只要改父亲节点的ID就可以了。

对于B来说,不知道这个所有父亲的层数(也就是树的深度),对于数据库表的设计上有难度,如果确定了层数(比如身份证号那样的省市信息),还是比较方便的。对于改动比较少的节点系统,还是比较合适,否则的话,要编写相关的改动方面的功能代码。

老潜水也不好。:D

to: superhc 谢谢关注,欢迎探讨。


一、树型结构的实现。

你说得没错,树型结构有多种实现方式,编码实现是很不错的一种,也很常用。

相比 ParentID 的方式,编码方式的优点可能在于,简单,也就是说,无需递归就能获得结构信息。应该说,对于很多的应用场景,这样的实现方式都是合适的而且功能足够。但是,编码方式带来的简单是有 TradeOff 的。

1.不够灵活,试想如果必须将某个子树移到另一个节点下,这需要 Update 某种编码的所有记录。
2.检索代价,试想如果你需要取得某个节点下的子树,这需要用 LIKE 来做查询,而 LIKE 的效率是最低的,当树比较大或者查询的次数比较多时,它会成为性能的瓶颈(这是我在实际应用中得到的经验)。
3.当某节点下面的数据频繁修改,编码序列如何产生和重用?

对权限系统而言,只要能实现功能,具体用哪一种方式来实现一棵树并不重要,但一定要根据实际应用的具体情况来予以选择。


二、组织结构的概念

你提到的“建立并维护企业中的组织结构”问题。这是一个非常好的问题,因为在目前的架构中,的确没有一个很直观的概念方式来映射它。

但,我觉得再次引入 Role 是不可取的,关于 Group 与 Role 的取舍,请看我的第二篇回帖《 Role 的必要性》。思路的具体“演化过程”你可以再细看一下那篇帖子,需要说明的是,这只是我自己的个人看法,或许是错的。

关于组织结构的概念,我初步的想法是,将组织结构看作是权限控制中的一个重要“维度”(肯定不会是唯一的维度)。也是说,考虑在 Group 中引入“维度”属性,组织结构是一个维度(比如叫人事系统),其他的还有另外的维度(比如,信息发布系统、广告管理系统)。不过,这个想法尚未考虑成熟。等我理出一个大概,说不定会再补充一篇帖子说明我的想法。

anyway, 谢谢你富有启发的探讨。

to: geshe
呵呵,高手出手了啊,言简意赅,一语中的,就是不同凡响。

to: ryo
Sorry, 我的失误, power2acl 应该是 pow2acl 网址如下:
http://sourceforge.net/projects/pow2acl

按照我的意思来看:
role与privilege是一一对应的关系,

group则是role的集合

其实这里的group并不是传统意义上的用户组,而是一个角色组。

不知这样有道理否?

我觉得Role到底需不需要, 要看运行系统的规模而定, 如果整个系统做的事情可以看成是一个项目, 各个部分关联较多, 较紧密, 那没有Role是比较合适的。 但是当一个系统的规模已经非常庞大时,即便加上组的继承机制也会显得力不从心。 如果一个用户在一个项目里是项目经理, 有统筹规划的权利, 而同时又是另一个项目的Supervisor,只有监控的权利,而这两个项目有没有什么关系,由两组不同的人来完成, 这个情况下不用Role处理的话就会有些吃力了。

另外我觉得不利用ACL, 不能动态解析对象与权限的宏表达的权限系统,始终不会非常灵活和强大。

如果业务逻辑还是需要通过编码来实现的话,那这个系统的价值也会大打折扣了。

不好意思版主, 不知道这个帖子怎么修改呀?
上面最后一句可能说的不恰当, 我是想说对应权限控制的业务逻辑,:P
整个业务逻辑想都通过配置体现当然好了, 但是确实不现实。

看了上面各位大虾的发言,很受启发,自己的项目也会遇到权限问题,故有点想法,拿出来大家看看。

从我自己的经验来看,一般应用系统的用户都是有清晰的上下级关系的。比如会计的领导是财务主管,财务主管的领导是主管财务的副经理,副经理的领导是经理,等等。许多活动都会使用到这种上下级的关系,比如,财务主管只能看到他手下的会计的工作报告,而不能看到其他人的。这种权限控制的应用很普遍,就不再举例了。因此我认为,user不是相互平行,相互独立的,而是有上下级关系的。

当然,让user之间有上下级关系是不合逻辑的。因为某个人不是天生就是其他人的领导,而是因为他们职位的不同,是职位之间有级次而不是人之间有级次(我们要提倡人人平等,呵呵)。那就引入positon吧,让user之间是平等的(本来就是:)),position之间有上下级关系。一个user可以对应多个position,因为有身兼多职的情况(这才是引入position的真正原因)。

那这种user-position不是和user-group一样了?不一样!
第一,position之间有明确的、有意义的上下级关系,position有实际意义,而group对此要求不严格(这也是group的长处和特色);
第二,position之间的权限是自下而上传递的,下级的权限上级自动拥有,而不是相反,group也能实现,但比较勉强;
第三,我觉得两者的设计思想不同,我的实现是基于关系数据库的,position之间用层次码实现,而jackyz的oo的思想。

总结一下:有三个实体
1、User。没什么说的
2、Position。有上下级关系,一个position只能有一个父position。user-position之间是多对多。可以一人身兼多职。
3、Operate。

至于group和role,我觉得只是一种辅助,不是必要的。如果系统的position很多,逐个授权违背了“简单,方便”的目的(jackyz语),那就引入group,将权限相同的position组成一个group进行集中授权。role也一样,是某一类Operate的集合,是为了简化针对多个Operate的操作。