|
锁定老贴子 主题:一个rbac的权限管理模型,大家讨论讨论
该帖已经被评为精华帖
|
|
|---|---|
| 作者 | 正文 |
|
最后更新时间:2005-08-04
基于简洁的原因,模型中的role没有层次结构。
声明:JavaEye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
|
|
| 返回顶楼 | |
|
最后更新时间:2005-08-05
我也用代码简单写一下,在Permission/Resource那里没这么多关系,Role扩展了一下,分三类角色,全局/非全局/归属具体Group。
接口定义: [code:1]public interface SecurityRole extends SecurityObject { public List getScorpioleonPermissions(); public List getSecurityUsers(); public SecurityGroup getSecurityGroup(); public boolean isGlobalRole(); } public interface SecurityGroup extends SecurityObject { public List getSecurityUsers(); } public interface SecurityUser extends SecurityObject { public SecurityGroup getSecurityGroup(); public List getSecurityRoles(); } public interface ScorpioleonPermission extends SecurityObject { public boolean equals(String operationIndentity, String resourceClassName); public boolean isAnonymousPermission(String operationIndentity, String resourceClassName); } public interface SecurityOperation extends SecurityObject { public String getIdentity(); public SecurityOperation getInstance(String operationIdentity); } public interface SecurityResource extends SecurityObject { public SecurityGroup getSecurityGroup(); public Class getSecurityClass(); }[/code:1] service code: [code:1]public class SecurityManager { private ScorpioleonPermission scorpioleonPermission; public void setPermission(ScorpioleonPermission scorpioleonPermission) { this.scorpioleonPermission = scorpioleonPermission; } public boolean hasPermission(SecurityUser user, SecurityOperation operation, SecurityResource resource) { return validate(resource) ? hasPermission(user, operation, resource, resource.getSecurityGroup()) : false; } public boolean hasPermission(SecurityUser user, SecurityOperation operation, SecurityResource resource, SecurityGroup group) { return validate(resource) ? hasPermission(user, operation, resource.getSecurityClass().getName(), group) : false; } public boolean hasPermission(SecurityUser user, SecurityOperation operation, String resourceClassName, SecurityGroup group) { if (!(validate(operation) && resourceClassName != null)) { return false; } if (scorpioleonPermission.isAnonymousPermission(operation.getIdentity(), resourceClassName)) { return true; } if (!(validate(user) && validate(group))) { return false; } List roles = user.getSecurityRoles(); if (roles != null) { for (int i = roles.size() - 1; i >= 0; i--) { SecurityRole role = (SecurityRole)roles.get(i); if (role.isAvailable()) { if (hasPermission(role, operation.getIdentity(), resourceClassName)) { if (role.getSecurityGroup() != null) { if (role.getSecurityGroup().equals(group)) { return true; } } else if (role.isGlobalRole()) { return true; } else if (user.getSecurityGroup().equals(group)) { return true; } } } } } return false; } public boolean hasPermission(SecurityRole role, String operationIndentity, String resourceClassName) { return role == null ? false : containPermission(role.getScorpioleonPermissions(), operationIndentity, resourceClassName); } protected boolean validate(SecurityObject securityObject) { return (securityObject != null && securityObject.isAvailable()) ? true : false; } public boolean containPermission(List permissions, String operationIndentity, String resourceClassName) { if (permissions == null) { return false; } for (int i = permissions.size() - 1; i >= 0; i++) { ScorpioleonPermission rolePermission = (ScorpioleonPermission)permissions.get(i); if (rolePermission.isAvailable() && rolePermission.equals(operationIndentity, resourceClassName)) { return true; } } return false; } }[/code:1] 接下来之需要实现对应的接口以及为AOP编写SecurityInterceptor了 |
|
| 返回顶楼 | |
|
最后更新时间:2005-08-05
lllyq:
你的模型对类进行了保护,而上面的模型对类的实例进行了保护。 但是,我们在很多时候是需要对类的实例进行保护的。 看看能不能综合一下,既考虑粗粒度的类保护,又考虑细粒度的类实例保护。 |
|
| 返回顶楼 | |
|
最后更新时间:2005-08-05
那就拓展一下:
[code:1]public interface SecurityResource extends SecurityObject { public SecurityGroup getSecurityGroup(); public Class getSecurityClass(); }[/code:1] 改为 [code:1]public interface SecurityResource extends SecurityObject { public String getIdentity(); public SecurityGroup getSecurityGroup(); public Class getSecurityClass(); }[/code:1] SecurityManager 增加方法 例如对应于 [code:1]public boolean hasPermission(SecurityUser user, SecurityOperation operation, SecurityResource resource) ;[/code:1] 可有 [code:1]public boolean hasPermission(SecurityUser user, SecurityOperation operation, SecurityResource resource, String resourceIdentity) { if (hasPermission(SecurityUser user, SecurityOperation operation, SecurityResource resource) { return true; } else { .......permission.equals(operationIdentity, resourceClassName, resourceIdentity); ...... } }[/code:1] |
|
| 返回顶楼 | |
|
最后更新时间:2005-08-06
lllyq:
你的模型很简洁,但有一点不尽如人意的地方。 在你的模型中,resource和operation是分开的。 而resource和operation实际上是相关的。比如说,对于一个工作流的流程,有开始、终止、任务分配等权限,而这些权限跟其他资源的权限显然不同,不能应用到其他资源上。这就需要管理员有相关的经验,才不会在分配权限时出错。 |
|
| 返回顶楼 | |
|
最后更新时间:2005-08-07
jander 写道 lllyq:
你的模型很简洁,但有一点不尽如人意的地方。 在你的模型中,resource和operation是分开的。 而resource和operation实际上是相关的。比如说,对于一个工作流的流程,有开始、终止、任务分配等权限,而这些权限跟其他资源的权限显然不同,不能应用到其他资源上。这就需要管理员有相关的经验,才不会在分配权限时出错。 有很多方法可以控制某个资源允许有哪些操作,你也可以给ecurityResource加上getAvariableOperators(),不过我觉得还不如在管理权限的地方用getAvariableOperatorsByResource(SecurityResource resource)会好一点,因为这部分配资源的功能是相对独立的,可以不必在这个模型中反映,所以我觉得不必修改模型 |
|
| 返回顶楼 | |
|
最后更新时间:2005-08-07
lllyq 写道 有很多方法可以控制某个资源允许有哪些操作,你也可以给ecurityResource加上getAvariableOperators(),不过我觉得还不如在管理权限的地方用getAvariableOperatorsByResource(SecurityResource resource)会好一点,因为这部分配资源的功能是相对独立的,可以不必在这个模型中反映,所以我觉得不必修改模型 Operation和Resource有关系,当然要反映出来。 另外,我觉得你的模型,从角色出发定义角色各个资源的权限很方便。但是,要从资源开始,定义一个资源的相关角色的权限就麻烦了。比如说,我要定义一个目录的权限,应该从目录管理中来定义。而不是从角色管理中来定义,因为方便一些。 还有,执行起来也没有我提出来的模型有效率。在你的模型中一个权限的相关操作在数据库中是一个集合,而我提出的模型中,一个权限在数据库中的相关操作仅仅用一个整形的mask标记。 |
|
| 返回顶楼 | |
|
最后更新时间:2005-08-08
Operation和Resource不是必然关系,可以在实现类自定义。
引用 “定义一个目录的权限,应该从目录管理中来定义”
你是指授权给role还是直接授权给user,授权给role跟role获得resource的权限没什么差别。要是授权给user,那就不是纯rbac了,模型中的SecurityUser需要加getPermissions的方法,SecurityManager需要多一点判断,不难。 另外,int mask效率高,我想map role,group, resource type的信息还可以(我觉得也不好扩展),但是map resource id(细粒度),位数恐怕不够吧? |
|
| 返回顶楼 | |
|
最后更新时间:2005-08-08
lllyq 写道 Operation和Resource不是必然关系,可以在实现类自定义。
你是指在Resource的实现类中定义? lllyq 写道 你是指授权给role还是直接授权给user,授权给role跟role获得resource的权限没什么差别。要是授权给user,那就不是纯rbac了,模型中的SecurityUser需要加getPermissions的方法,SecurityManager需要多一点判断,不难。
我是说,在你的模型中,从某个资源得到各个角色的授权情况,比较麻烦。 lllyq 写道 另外,int mask效率高,我想map role,group, resource type的信息还可以(我觉得也不好扩展),但是map resource id(细粒度),位数恐怕不够吧? mask仅仅表示操作,看看上面的模型,每一类资源都有一个相应的Permission的子类,角色对一个资源的操作权限,仅仅用一个int类型的mask就表示了。下面是Permissiion的源码。 另外,下面简单画了一下你的模型。去除了Group和Role之间的关系,因为主要注意的是授权模型。在你的模型中,只需要编写一个Permission类就可以了,不知道我理解的对不对? [code:1] import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; /** * Class represents permissions on any {@link SecuredObject}. Every type of {@link SecuredObject}must has own subclass of this class which represent set of allowed permissions. * * @author Gordienko_m * @author Semochkin_v */ public class Permission implements Serializable { private static byte MASK_POWER = 0; public static final Permission READ = new Permission(MASK_POWER++, "permission.read"); public static final Permission UPDATE_PERMISSIONS = new Permission(MASK_POWER++, "permission.update_permissions"); private static final Permission[] ALL_PERMISSIONS = { READ, UPDATE_PERMISSIONS }; private static final String NO_PERMISSION_NAME = "permission.none"; private String name; private long mask; protected Permission(byte maskPower, String name) { this.mask = mask(maskPower++); this.name = name; } /** * Creates permission with mask==0 */ public Permission() { this.mask = 0; this.name = NO_PERMISSION_NAME; } public long getMask() { return mask; } public String getName() { return name; } private static final long mask(long maskPower) { return (long) Math.pow(2, maskPower); } public static long getMask(Permission[] per) { long mask = 0; for (int i = 0; i < per.length; i++) { mask |= per[i].getMask(); } return mask; } public Permission[] getPermissions(long mask) { List permissionsList = new ArrayList(); Permission[] p = getAllPermissions(); for (int i = 0; i < p.length; i++) { if ((mask & p[i].getMask()) == p[i].getMask()) { permissionsList.add(p[i]); } } return (Permission[]) permissionsList.toArray(new Permission[permissionsList.size()]); } /** * Returns an array of all permissions that executor may have on type of secured object this class represents. This method must be overriden in subclass */ public Permission[] getAllPermissions() { return (Permission[]) ALL_PERMISSIONS.clone(); } public boolean equals(Object obj) { if (obj == null) return false; if (this == obj) return true; if (!(this.getClass().isInstance(obj))) return false; Permission p = (Permission) obj; if (getMask() == p.getMask() && getName().equals(p.getName())) return true; return false; } public int hashCode() { int result = 17; result = 37 * result + (int) (getMask() ^ (getMask() >>> 32)); result = 37 * result + getName().hashCode(); return result; } public String toString() { return mask + " " + name; } public static Permission[] mergePermissions(Permission[] p1, Permission[] p2) { Set set = new HashSet(Arrays.asList(p1)); set.addAll(Arrays.asList(p2)); return (Permission[]) set.toArray(new Permission[set.size()]); } public static Permission[] subtractPermissions(Permission[] p1, Permission[] p2) { Set set = new HashSet(Arrays.asList(p1)); set.removeAll(Arrays.asList(p2)); return (Permission[]) set.toArray(new Permission[set.size()]); } } [/code:1] |
|
| 返回顶楼 | |
|
最后更新时间:2005-09-22
我最近也在看权限方面的设计,很多地方不是很明白
楼上,你的模型里面的Group,感觉没有什么作用啊? Group难道就是单纯的归类Users? 看到很多介绍权限的所谓的高手的文章,都提到Group和Operator是多对多的 但是,我看不到Group是怎么和Operator联系起来的阿? 请指点 |
|
| 返回顶楼 | |






