锁定老帖子 主题:一个rbac的权限管理模型,大家讨论讨论
该帖已经被评为精华帖
|
|
---|---|
作者 | 正文 |
发表时间:2005-08-04
声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2005-08-05
我也用代码简单写一下,在Permission/Resource那里没这么多关系,Role扩展了一下,分三类角色,全局/非全局/归属具体Group。
接口定义: 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();; } service code: 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; } } 接下来之需要实现对应的接口以及为AOP编写SecurityInterceptor了 |
|
返回顶楼 | |
发表时间:2005-08-05
lllyq:
你的模型对类进行了保护,而上面的模型对类的实例进行了保护。 但是,我们在很多时候是需要对类的实例进行保护的。 看看能不能综合一下,既考虑粗粒度的类保护,又考虑细粒度的类实例保护。 |
|
返回顶楼 | |
发表时间:2005-08-05
那就拓展一下:
public interface SecurityResource extends SecurityObject { public SecurityGroup getSecurityGroup();; public Class getSecurityClass();; } 改为 public interface SecurityResource extends SecurityObject { public String getIdentity();; public SecurityGroup getSecurityGroup();; public Class getSecurityClass();; } SecurityManager 增加方法 例如对应于 public boolean hasPermission(SecurityUser user, SecurityOperation operation, SecurityResource resource); ; 可有 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);; ...... } } |
|
返回顶楼 | |
发表时间: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类就可以了,不知道我理解的对不对? 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();]);; } } |
|
返回顶楼 | |
发表时间:2005-09-22
我最近也在看权限方面的设计,很多地方不是很明白
楼上,你的模型里面的Group,感觉没有什么作用啊? Group难道就是单纯的归类Users? 看到很多介绍权限的所谓的高手的文章,都提到Group和Operator是多对多的 但是,我看不到Group是怎么和Operator联系起来的阿? 请指点 |
|
返回顶楼 | |