本站首页    管理页面    写新日志    退出


«September 2025»
123456
78910111213
14151617181920
21222324252627
282930


公告
 本博客在此声明所有文章均为转摘,只做资料收集使用。

我的分类(专题)

日志更新

最新评论

留言板

链接

Blog信息
blog名称:
日志总数:1304
评论数量:2242
留言数量:5
访问次数:7606468
建立时间:2006年5月29日




[Hibernate]Acegi+hibernate 动态实现基于角色的权限管理(2)
软件技术,  电脑与网络

lhwork 发表于 2006/6/13 11:32:58

解决方法: 1: 开发基于数据库的保护资源。 看过acegi的源代码就会知道,对保护资源的定义是通过实现ObjectDefinitionSource这个接口来实现的,而且acegi为我们提供了默认实现的抽象类 500)this.width=500'>public abstract class AbstractMethodDefinitionSource 500)this.width=500'>500)this.width=500'>    implements MethodDefinitionSource 500)this.width=500'>{ 500)this.width=500'>    //~ Static fields/initializers ============================================= 500)this.width=500'>500)this.width=500'>    private static final Log logger = LogFactory.getLog(AbstractMethodDefinitionSource.class); 500)this.width=500'>500)this.width=500'>    //~ Methods ================================================================ 500)this.width=500'>500)this.width=500'>    public ConfigAttributeDefinition getAttributes(Object object) 500)this.width=500'>500)this.width=500'>        throws IllegalArgumentException 500)this.width=500'>{ 500)this.width=500'>        Assert.notNull(object, "Object cannot be null"); 500)this.width=500'>500)this.width=500'>500)this.width=500'>        if (object instanceof MethodInvocation) 500)this.width=500'>{ 500)this.width=500'>            return this.lookupAttributes(((MethodInvocation) object).getMethod()); 500)this.width=500'>        } 500)this.width=500'>500)this.width=500'>500)this.width=500'>        if (object instanceof JoinPoint) 500)this.width=500'>{ 500)this.width=500'>            JoinPoint jp = (JoinPoint) object; 500)this.width=500'>            Class targetClazz = jp.getTarget().getClass(); 500)this.width=500'>            String targetMethodName = jp.getStaticPart().getSignature().getName(); 500)this.width=500'>            Class[] types = ((CodeSignature) jp.getStaticPart().getSignature()) 500)this.width=500'>                    .getParameterTypes(); 500)this.width=500'>500)this.width=500'>500)this.width=500'>            if (logger.isDebugEnabled()) 500)this.width=500'>{ 500)this.width=500'>                logger.debug("Target Class: " + targetClazz); 500)this.width=500'>                logger.debug("Target Method Name: " + targetMethodName); 500)this.width=500'>500)this.width=500'>500)this.width=500'>                for (int i = 0; i < types.length; i++) 500)this.width=500'>{ 500)this.width=500'>500)this.width=500'>                    if (logger.isDebugEnabled()) 500)this.width=500'>{ 500)this.width=500'>                        logger.debug("Target Method Arg #" + i + ": " 500)this.width=500'>                                + types[i]); 500)this.width=500'>                    } 500)this.width=500'>                } 500)this.width=500'>            } 500)this.width=500'>500)this.width=500'>500)this.width=500'>            try 500)this.width=500'>{ 500)this.width=500'>                return this.lookupAttributes(targetClazz.getMethod(targetMethodName, types)); 500)this.width=500'>500)this.width=500'>            } catch (NoSuchMethodException nsme) 500)this.width=500'>{ 500)this.width=500'>                throw new IllegalArgumentException("Could not obtain target method from JoinPoint: " + jp); 500)this.width=500'>            } 500)this.width=500'>        } 500)this.width=500'>500)this.width=500'>        throw new IllegalArgumentException("Object must be a MethodInvocation or JoinPoint"); 500)this.width=500'>    } 500)this.width=500'>500)this.width=500'>500)this.width=500'>    public boolean supports(Class clazz) 500)this.width=500'>{ 500)this.width=500'>        return (MethodInvocation.class.isAssignableFrom(clazz) 500)this.width=500'>        || JoinPoint.class.isAssignableFrom(clazz)); 500)this.width=500'>    } 500)this.width=500'>500)this.width=500'>500)this.width=500'>    protected abstract ConfigAttributeDefinition lookupAttributes(Method method); 500)this.width=500'>} 500)this.width=500'>我们要做的就是实现它的 protected abstract ConfigAttributeDefinition lookupAttributes(Method method);方法, 以下是我的实现方法,大致思路是这样,通过由抽象类传来的Method 对象得到 调 用这个方法的 包名,类名,方法名 也就是secureObjectName, 查询数据库并将结果映射为Function 也就是secureObject ,由于Function 与 Role 的多对多关系 可以得到 Function所对应的 Roles ,在将role 包装成GrantedAuthority (也就是acegi中的角色)。其中由于频繁的对数据库的查询 所以使用Ehcache 来作为缓存。   1 package sample.auth;   2   3 import java.lang.reflect.Method;   4 import java.util.ArrayList;   5 import java.util.Arrays;   6 import java.util.Collection;   7 import java.util.Iterator;   8 import java.util.List;   9 import java.util.Set;  10  11 import org.acegisecurity.ConfigAttributeDefinition;  12 import org.acegisecurity.ConfigAttributeEditor;  13 import org.acegisecurity.GrantedAuthority;  14 import org.acegisecurity.GrantedAuthorityImpl;  15 import org.acegisecurity.intercept.method.AbstractMethodDefinitionSource;  16 import org.springframework.util.Assert;  17  18 import sample.auth.cache.AuthorityBasedFunctionCache;  19 import sample.auth.cache.info.FunctionByNameCache;  20 import sample.dao.IBaseDao;  21 import sample.mappings.function.Function;  22 import sample.mappings.role.Role;  23  24 public class DatabaseDrivenMethodDefinitionSourcew extends  25                 AbstractMethodDefinitionSource {  26          27         // baseDao 提供通过HIbenate对数据库操作的实现  28         private IBaseDao baseDao;  29         // AuthorityBasedFunctionCache 通过Function 查 Role 时缓存  30         private AuthorityBasedFunctionCache cache;  31         // FunctionByNameCache 由反射到的方法名查找 数据库对应的Function 时的缓存  32         private FunctionByNameCache functionCache;  33  34         public FunctionByNameCache getFunctionCache() {  35                 return functionCache;  36         }  37  38         public void setFunctionCache(FunctionByNameCache functionCache) {  39                 this.functionCache = functionCache;  40         }  41  42         protected ConfigAttributeDefinition lookupAttributes(Method mi) {  43          44                 Assert.notNull(mi,"lookupAttrubutes in the DatabaseDrivenMethodDefinitionSourcew is null");  45                 String secureObjectName=mi.getDeclaringClass().getName() +"."+ mi.getName();  46                 //Function 为数据库中保护资源的映射  47                 Function secureObject=functionCache.getFunctionByCache(secureObjectName);  48  49                 if(secureObject==null)//if secure object not exist in database  50                 {  51                         secureObject=(Function)baseDao.loadByKey(Function.class, "protectfunction", secureObjectName);  52                         functionCache.putFunctionInCache(secureObject);  53                 }  54                      55                 if(secureObject==null)  56                         Assert.notNull(secureObject,"secureObject(Function) not found in db");  57                 //retrieving roles associated with this secure object  58                  59                 Collection roles = null;  60                 GrantedAuthority[] grantedAuthoritys = cache.getAuthorityFromCache(secureObject.getName());  61                 // 如果是第一次 cache 为空  62                 if(grantedAuthoritys == null){  63                          64                         Set rolesSet = secureObject.getRoles();  65                         Iterator it = rolesSet.iterator();  66                         List list = new ArrayList();  67                         while(it.hasNext()){  68                                  69                                 Role role = (Role)it.next();  70                                 GrantedAuthority g = new  GrantedAuthorityImpl(role.getName());  71                                 list.add(g);         72                         }  73                         grantedAuthoritys = (GrantedAuthority[])list.toArray(new GrantedAuthority[0]);  74                         cache.putAuthorityInCache(secureObject.getName(),grantedAuthoritys);  75                         roles = Arrays.asList(grantedAuthoritys);  76                 }else{  77                          78                         roles = Arrays.asList(grantedAuthoritys);  79                 }  80                  81                 if(!roles.isEmpty()){  82                         ConfigAttributeEditor configAttrEditor=new ConfigAttributeEditor();  83                         StringBuffer rolesStr=new StringBuffer();  84                         for(Iterator it = roles.iterator();it.hasNext();){  85                                 GrantedAuthority role=(GrantedAuthority)it.next();  86                                 rolesStr.append(role.getAuthority()).append(",");  87                         }  88  89                         configAttrEditor.setAsText( rolesStr.toString().substring(0,rolesStr.length()-1) );  90                         ConfigAttributeDefinition configAttrDef=(ConfigAttributeDefinition)configAttrEditor.getValue();  91                         return configAttrDef;  92                 }  93  94                 Assert.notEmpty(roles,"collection of roles is null or empty");  95                 return null;  96                  97  98         }  99 100         public Iterator getConfigAttributeDefinitions() { 101                 102                 return null; 103         } 104 105 106         public IBaseDao getBaseDao() { 107                 return baseDao; 108         } 109 110 111         public void setBaseDao(IBaseDao baseDao) { 112                 this.baseDao = baseDao; 113         } 114 115         public AuthorityBasedFunctionCache getCache() { 116                 return cache; 117         } 118 119         public void setCache(AuthorityBasedFunctionCache cache) { 120                 this.cache = cache; 121         } 122 123 } 124 2:定义 基于方法的 自定义标志 通 过以上的分析 , 要想使用acegi 做页面的显示控制仅仅靠角色(Role)是不行的,因为用户可能随时定义出新的角色,所以只能 基于方法(Function)的控制。可是acegi 只是提供了基于 角色的 接口GrantedAuthority ,怎么办?  ,如法炮制。 首先定义出我们自己的GrantedFunction,实现也雷同 GrantedAuthorityImpl  1 package sample.auth;  2  3 import java.io.Serializable;  4 public class GrantedFunctionImpl implements GrantedFunction , Serializable{  5  6     private String function;  7  8     //~ Constructors ===========================================================  9 10     public GrantedFunctionImpl(String function) { 11         super(); 12         this.function = function; 13     } 14 15     protected GrantedFunctionImpl() { 16         throw new IllegalArgumentException("Cannot use default constructor"); 17     } 18 19     //~ Methods ================================================================ 20 21     public String getFunction() { 22         return this.function; 23     } 24 25     public boolean equals(Object obj) { 26         if (obj instanceof String) { 27             return obj.equals(this.function); 28         } 29 30         if (obj instanceof GrantedFunction) { 31             GrantedFunction attr = (GrantedFunction) obj; 32 33             return this.function.equals(attr.getFunction()); 34         } 35 36         return false; 37     } 38 39     public int hashCode() { 40         return this.function.hashCode(); 41     } 42 43     public String toString() { 44         return this.function; 45     } 46 47 } 48 


阅读全文(2784) | 回复(0) | 编辑 | 精华
 



发表评论:
昵称:
密码:
主页:
标题:
验证码:  (不区分大小写,请仔细填写,输错需重写评论内容!)



站点首页 | 联系我们 | 博客注册 | 博客登陆

Sponsored By W3CHINA
W3CHINA Blog 0.8 Processed in 0.063 second(s), page refreshed 144759384 times.
《全国人大常委会关于维护互联网安全的决定》  《计算机信息网络国际联网安全保护管理办法》
苏ICP备05006046号