我也请教一个关于权限设计方面的问题

03-10-21 ninsky
首先表示一下奇怪:我以前在这注册的号是不是给删除了,虽然我确实很久没在这发言了!

我现在在做一个系统,一个类似信息发布的东东,本来也无所谓,可没想到用户提出了许多BT的要求,尤其是权限方面,本来照我的常规思维,这种东东一般也就是划分几个角色,划分几个信息的发布模块等等也就行了,甚至公司都有现成的东西直接用。
可没想到客户的要求比较刁钻。我先说说系统的大概模样。
信息发布吗,首先当然要划分信息的类别和层次,而这层次是不定的,可能是两三层,也可能是十层、八层(没这么变态吧^_^),其实就类似与windows的资源管理器的样式,目录里面含着文件,而文件又有可能和目录平级的说,这是显示方面大概要显示的东东。现在说说他们在权限控制方面的要求,某个用户登录系统之后,这些目录文件(使用的是资源管理器类似的样式,左边一颗树,右边基本信息列表)将需要根据用户权限的不同而不同(有的目录文件显示,有的不显示的说),当然对于不同的记录用户也需要有不同的增删改权限,列表虽然都能看见,不过有的记录他可以修改却不可以删除,有的却连修改都不许了,当然还有其他的一下操作方式的控制。更为变态的是,要求点击某条记录(或目录、或文件)时弹出的信息查看页面对于不同权限的用户也需不同,即某些字段可以显示,某些字段不能显示(my god,还是把我回收了得了),这就要求在后台的管理方面有着灵活的操作,当然用户也要求了,本着易用性的原则,管理员可以适当选择是对一条条记录赋权还是对一批记录赋权。

说了这么多,不知道各位能否看明白?

我开始的想法是定义组,将某些权限相同的用户赋为一组,然后对记录赋权时根据组进行选择而不用对每个人进行选择,这样就不需对个人进行操作(即使一个人也给他搞个组),这样对组配置改组可以对记录有那些权限,可以显示记录的那些字段,然后针对记录选择组(一个用户可能属于多个组,如有重复,则以用户能获得的最大权限为主)。
不过后来一想,加入某些记录只是针对个人的,如果也这么做的话,会死人的啊,组的数量就太多了。

不过用户的这些要求说到底其实也挺合理,不过实现起来也确实挺头疼,反正我头疼了一个下午了,几张目录文件的表画好后,后台权限方面我死活下不了手了:(
我也希望能够趁这个系统的机会把这个权限管理好好核计核计,反正尽量希望能在设计阶段就考虑完善,最好能将权限这块尽量独立出来,将来在其他系统中可以比较方便地移至(估计也没那个信息系统有这么繁琐的要求了,本来不大的玩意,愣是让他们搞大发了)

但本人在设计方面是个新手,所以感觉难度实在挺大,还是先听听各位在座的高论先,请指教一下该如何下手,信息表与权限表该如何关联,如果有谁做过这方面的东东的话,那就更好了。

所有经验、方法、建议,在下一律欢迎,还请各位不吝赐教,我实在是头都大了

3
iceant
2003-10-22 00:36
1. 对"有的目录文件显示,有的不显示的"疑问
具体到一个目录下的文件是可以控制显示与不显示,但是对目录而言不适合做这样的控制。为什么?假如用户只对 1.1.1 目录有访问权限,那么 1.1 的目录级别要不要体现出来?如果只列用户有权限的目录,那怎么能看得出是 1.1.1 的那个目录?

2.组与用户
你的应用实际上是动态责任确定的应用,在程序规划与实施阶段没有办法获知有哪些角色能操作哪些对象;
另外,权限设计不可过于复杂,否则管理员也会弄不清自己分配的权限是什么样的,最少我自己加个两三层的东东就会头晕。
因此我建议你做基于 ACL 的控制。你提到了想使用组的概念,但是你想为一个人也定义一个组,我认为没有必要,完全可以是用户(User)与 Subject(Folder|Documents)直接对应。如果只能有一个人操作一个目录的文件修改,那你直接授权给某个人,和修改 Role-User Map 关系的维护量没有多大的差别。但是如果对一个目录同一种 Permission 的操作分别授权给不同的用户,维护起来肯定没有建个组或一个角色来得简单。

因此,我的选择是直接使用 Subject,Group,User 的三级关系。
这里先解释几个名词:
Subject: 各种目录,文件等对象
Group: 用户集合
User:用户
Operation: 对 Subject 的某种具体操作,如 Visit,Modify,Delete 等
Permission: 是 Subject 与 Operation 的组合,如:指对某个目录的Visit操作

OK, 那让我们来建几个表吧:
Permissions_Table(
subject varchar(20),--对应目录或文件的ID
user_name varchar(10), -- USER-Subject ACL
group_name varchar(10), -- Group -Subject ACL
operation_type int, --1:visit,2:modify 4:delete,3:visit+modify,5:delete+visit,6:delete+modify,7:visit+modify+delete
subject_type int, --1:dir,2:document
)

user_group_table(
user_name varchar(10),
group_name varchar(10),
primary key(user_name,group_name)
)

再下面....
我相信你有能力做完的....

ninsky
2003-10-22 10:02
感谢iceant,你的意见给了我一个思路,某些地方我确实走入了歧途,也盲目的想设计一个通用的东东(估计这就是过度设计)

不过我还想请教一下就是,对于控制到字段的权限模式你能否也提供一点建议呢

我现在就是想多找些人,听一下别人的意见,然后再自己综合一下,希望能够尽量好的实现这套权限管理功能

希望各位多多发言,希望能对我这已经困累欲绝的大脑来点刺激

再次感谢iceant,jdon的讨论风气是我转的几个论坛中最好的一个了

iceant
2003-10-22 11:16
"对于控制到字段的权限模式你能否也提供一点建议呢"

什么叫控制到字段的权限模式?

ninsky
2003-10-22 12:19
> "对于控制到字段的权限模式你能否也提供一点建议呢"
>
> 什么叫控制到字段的权限模式?

就是对于某个表中的某些字段是可以显示的,而某些是不显示的

当然有个方法是将所有的表的字段及相关的描述信息放到一个数据字典表中,然后对数据字典进行一些相关的赋权操作,不过这样作要求数据字典和所有的表的字段同步

不过总感觉这种方法并不是太好,不过我也没想到其他的方法

iceant
2003-10-22 12:29
能不能详细说说你的应用情景? 举个例子

ninsky
2003-10-22 13:41
> 能不能详细说说你的应用情景? 举个例子

用户、单位等信息存储在LDAP中,而且是远程的,我的系统虽说取的是LDAP中的用户、单位信息,可是还得提供额外的用户、单位增加功能,也就是说在读取用户、单位信息时要将LDAP中的信息与自己增加的用户、单位信息汇合,重新进行树状排列(这个地方采取生成XML树的方式,不知效果如何),与此同时还要判断当前用户的权限,以便控制各节点是否显示(这些节点可能是单位,也可能是个人)。

然后对各个节点显示的信息还得读取控制权限,那些信息可以显示,那些不能显示,另外对各个信息的操作权限也有控制,对某条信息是增、删、改,还是仅仅查看。而对于某条记录的详细信息,又需控制某个字段是否显示,等等等等,如此这般

我的初步构想:
划分功能点:功能模块(不同用户有不同的操作模块,如我们一般程序顶的菜单项,非LDAP和相关信息)、表结构(数据字典表,控制到字段权限时用)
操作(operate):增、删、改、查看
角色:赋功能模块,及相关操作
用户:赋角色
组:赋用户

算了,就说这点吧,我也晕了,现在思路很乱

iceant
2003-10-22 13:54
我的感觉是你对需求不明确,建义你回去和客户坐下来谈谈他们想要的东东。你可以把操作的界面画出来,然后问问客户是不是想这样操作,如果不是,怎么改动,最后要一个需求更改说明书(可能要你写,客户签字,这也是对你自己的一种保护!),说明确定下来的需求是什么。

所谓有的字段显示,有的字段不显示,多数情况下在程序设计与实施阶段都可以确定的,字段显示就表明用户拥有某种权限,如拥有了增删改员工信息权限的用户,就能看到 Submit 按钮,而一般用户就看不到这个按钮。

ninsky
2003-10-22 14:23
呵呵,不是submit,那些倒是好说:)
例如显示页面中,有a、b、c、d等项,甲进入后可能会看到a、b项,而乙可能就是看到b、d、c等项了,是这么个意思

另:iceant你好像一直挂在坛里啊

iceant
2003-10-22 15:11
>>呵呵,不是submit,那些倒是好说:)
>>例如显示页面中,有a、b、c、d等项,甲进入后可能会看到a、b项,而
>>乙可能就是看到b、d、c等项了,是这么个意思

所以我请你举个例子来看看啊,不能实际把应用说清楚,就表示没有理解需求,没有理解需求,是不可能做出东西来的。即使做出来了,也只是不符合用户需求的东西。

这里你可以思考一下,为什么甲进入后看到的是 a,b? 是因为甲拥有了某种权限?是甲拥有了某种身份?乙需要拥有什么样的权限或身份才能看到b,d,c?

我觉得你总在说自己头痛,但并不知道自己为什么头痛。

>>另:iceant你好像一直挂在坛里啊

我今天放自己假,不想做事,所以有空。有时忙起来,可能一两个月也不会上网了~~~

ninsky
2003-10-22 16:28
其实,我真正头疼的是,我在考虑这个系统的设计的时候,思路老是飘到:如果这个系统更加通用的话该如何设计呢。以设计一个通用的,复用性强的系统为己任,头不疼才怪呢

是时候放弃这种想法了,都是让那帮老是让那帮高人把我害的^_^

anonymous
2003-10-23 12:37
我的项目中也碰到了类似的问题,即对于每个模块,对其下的各种资源的操作都是一种权限,比如新闻模块,“新闻”是一个资源,而“发布新闻”则是一个操作,而对“新闻的发布”则成了权限
在实际中,新闻若分部门,则“发布A部门的新闻”是一个实际的权限,在权限系统中,将个权限赋给某个角色即可,后面的都好办(参看本论坛中关于权限设计中的RBAC方面的讨论)

所以系统中比一般的RBAC多了以下表:
Resource
Operation

角色除了和权限对应外,还和资源实例对应,即如是A部门的则有RA角色,B的是RB,将这些角色分配给对应的用户或组后即完成授权。

在权限验证的时候通过当前用户和当前可操作角色(由当前模块所对应的资源实例来确定)来验证,ACL.checkPermission(user,resource,operation)

但难点在于模块和资源是变化的,新闻也许只需要一个部门ID就可以确定当前角色,对于复杂的应用如何获取当前模块资源实例并获取当前可操作角色则还没想出好的解决办法

继续thinking...

ninsky
2003-10-23 15:42
唉,我的问题与此类似,不过又稍微复杂了点

不知可否给我发个这方面的示例图啊,当然是非机密的
也好让我研究研究

以前自己写代码感觉挺爽的,再难的方法也都可以实现,可现在自己作设计,可真是感觉晕头转向的啊:(

努力、奋斗

littlebird
2003-10-24 16:24
看了这么多关于权限方面的讨论真是受益匪浅。
这里说说我的想法:
我认为对于多数企业应用项目,相对而言都不是很大的项目,权限管理部分是不是可以简化成:user *-->1 role 1-->* operate
用户可能有很多组织上的层次关系,但在这里可以将它压平,不论什么层次都直接和角色相关,而且只有一个角色
权限也可能有很多层次关系(比如新闻包括A、B或C部门的),这里也把它展开,让角色直接最底层的权限相关(如A部门新闻的修改权限)
根据用户获得它的角色,再根据角色获得它拥有权限的集合。

而group是用户的集合,把它加上会变得相当复杂;当然还可以有权限集合的概念也加入,那就更复杂了。

iceant
2003-10-25 11:07
我想理一理思路,看看 ACL 与 RBAC 的区别:

还是以部门新闻来讨论,对于静态授权,在系统设计做需求分析的时候,往往就可以
确定一个系统角色的种类,像新闻系统中,根据需求,可能会有新闻发布者(Publisher),
新闻审核者(Reviewer),新闻浏览者(Visitor),管理员(Manager)以及超级管理员(Administrator)。

在设计的时候我们也已经把这些角色与相应的一些 Operation 绑定在一起。
如:Publisher 拥有 Publish_Operation + Modify_Operation
Reviewer 拥有 Review_Operation + Modify_Operation + Delete_Operation
Visitor 拥有 Visit_Operation,
Manager 拥有 Create_News_System_Instance_Operation +
Modify_News_System_Instance_Operation +
Delete_News_System_Instance_Operation
Administrator 负责 Create_User_Operation+
Delete_User_Operation+
Assign_Permission_Operation+
Deassign_Permission_Operation +
Assign_Role_Operation+
Deassign_Role_Operation

在授权时,往往先为一个用户(USER),赋予一个角色,如: Manager. 这样,USER 就
拥有了对所有 News_Instance(也就是部门新闻) 操作的权限。
现在假设用户(UserA)访问 Create_News_System_Instance 功能来创建一个新的新闻实例,
叫做 采购部门新闻. 因为我们在设计的时候就确定,该功能只能由 Manager 来访问,
于是,系统中权限的判断部分会首先判断当前用户(UserA)是否 Manager 角色,是的话就允许
访问,否则显示没有授权的错误信息。

所以,对于 Manager 这样的应用:

[1] 在设计的时候,我们就将这样的角色与相应的 Permissions(A list of Subject-Operation pairs)
关联在一起了,这里的 Subject 是所有的新闻实例(News_Instance),Operation
就是 Create,Modify以及 Delete.

[2] 在授权的时候,超级管理员(Administrator)可以利用 Assign_Role_Operation 将用户(User)
与 Manager 这个角色关联起来。这样,User 就拥有了对所有新闻实例的 Create, Modify 以及 Delete
操作的权限。

[3] 在权限判断的时候,RBAC 系统首先判断当前用户是否是设计时确定的角色(这里是Manager),
如果是,就允许用户访问,否则就拒绝访问,并显示错误信息。


对于 Publisher 这样的角色有些不同,Publisher 这个角色只与 Operation 绑定在一起,并没有与
具体的 Subject 相关联,因此,在授权的时候,还需要指定相应的 Subject.

所以,对 Publisher 这样只能事先确定 Operation 的应用来说:

[1] 在设计的时候,我们只能确定该角色能进行哪些操作,而不能确定这些操作实施的对象。

[2] 在授权的时候:
[2.1] 首先将 Publisher 与 Subject 关联,如将 Publisher 与采购部门新闻关联产生:
采购部门新闻_News_Publisher 的角色
[2.2] Administrator 为用户(User)授于 采购部门新闻_News_Publisher 角色。从而 User
拥有了对"采购部门新闻"的发布权限

[3] 在权限判断的时候,用户访问 采购部门新闻_News_Publish_Operation, 系统首先判断
该用户是否 采购部门新闻_News_Publisher?如果是,就允许用户访问,否则就拒绝访问,
并显示错误信息。
这里用到的方法可能是这个样子:
boolean checkPermission(采购部门新闻,Publish_Operation,User){
List publishers = RBAC.findRole(new Permission(采购部门新闻,Publish_Operation));
if(publishers==null) return false;
for(Iterator it = publishers.iterator; it.hasNext();){
Role publisher = (Publisher)it.next();
if(publisher.isAssignedWithUser(User)){
return ture;
}
}
return false;
}

假如说,不采用 RBAC 的做法,考虑一下,使用 ACL,那又会是什么样子呢?
对于 Manager 那样能在设计时就确定 Subject 与 Operation 的角色,我认为没有必要考虑 ACL 了.
对于 Publisher 这样,只能事先确定 Operation 的角色,我们来做个对比.
权限系统要灵活,但是也要简洁,要不然就很可能导至失控。因为嵌套的层次太多,有可能发生不可
预知的情况. 有一天管理员可能会莫明的发现,怎么这个人会有这个权限的?
所以,我认为在 RBAC 里不支持 Role 的层级关系为妙。

好了,现在来看看 ACL 对 Publisher 应用
这里指的 ACL 是直接将 User 或 Group 与 Subject 关联的做法。
User 与 Subject 是多对多的情况,
Group 与 Subject 也是多对多的情况,
同样的,User 与 Group 也是多对多的情况。

现在,还是以采购部门新闻为例:

[1] 在授权的时候,可以有以下操作:
[1.1] 将 User 与 Subject 关联在一起,但是要指定相应的 Operation.
如: assignPermission(采购部门新闻,Publish_Operation,User)
[1.2] 将 Group 与 Subject 关联在一起:
如: assignPermission(采购部门新闻,Publish_Operation,Group)
[1.3] 将 User 与 Group 关联
如:
assignUserGroup(User,Group)

[2] 在权限判断的时候,用户访问 采购部门新闻_News_Publish_Operation,系统做如下检查:
boolean checkPermission(采购部门新闻,Publish_Operation,User){
boolean hasPermission = false;
// users include:
// 1. Permission direct assigned Users
// 2. The user assigned with the groups that assigned with permission
List users = getAssignedUsers(new Permission(采购部门新闻,Publish_Operation));
hasPermission=users.contains(User)?true:false;
}

猜你喜欢
4Go 1 2 3 4 下一页