Acegi+hibernate 动态实现基于角色的权限管理

Acegi+hibernate 动态实现基于角色的权限管理

 
可以看到它是通过读配置文件来判断执行某个方法所需要的角色的,再看这几句

< bean  id ="filterInvocationInterceptor"  class ="org.acegisecurity.intercept.web.FilterSecurityInterceptor" >  
      
< property  name ="authenticationManager" >< ref  bean ="authenticationManager" /></ property >  
      
< property  name ="accessDecisionManager" >< ref  local ="httpRequestAccessDecisionManager" /></ property >  
      
< property  name ="objectDefinitionSource" >  
         
< value >  
                            CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON 
                            PATTERN_TYPE_APACHE_ANT 
                            /index.jsp=ROLE_ANONYMOUS,ROLE_USER 
                            /hello.htm=ROLE_ANONYMOUS,ROLE_USER 
                            /logoff.jsp=ROLE_ANONYMOUS,ROLE_USER 
                            /switchuser.jsp=ROLE_SUPERVISOR 
                            /j_acegi_switch_user=ROLE_SUPERVISOR 
                            /acegilogin.jsp*=ROLE_ANONYMOUS,ROLE_USER 
                                /**=ROLE_USER 
         
</ value >  
      
</ property >  
   
</ bean >  
同样是将页面的访问权限写死在配置文件中,再来看看它的tag是如何处理的
< auth:authorize  ifAnyGranted ="ROLE_DELETE" >  
          
< href ="" > 删除 </ a >  
</ auth:authorize >  
可见它是要求我们对链接或者其他资源的保护时提供 用户角色,可是既然角色是用户自己添加的我们又如何来写死在这里呢?
还有就是它对用户验证默认使用的是jdbc,即 JdbcDaoImpl
< bean  id ="transactionManager"  class ="org.springframework.jdbc.datasource.DataSourceTransactionManager" >  
                
< property  name ="dataSource" >< ref  local ="dataSource" /></ property >  
        
</ bean >  
而我们希望基于Hibernate的Dao来实现。
可见仅仅使用现有的acegi 是 无法满足我们项目开发的需求的。
解决方法:

1: 开发基于数据库的保护资源。

看过acegi的源代码就会知道,对保护资源的定义是通过实现ObjectDefinitionSource这个接口来实现的,而且acegi为我们提供了默认实现的抽象类
public   abstract   class  AbstractMethodDefinitionSource 
    
implements  MethodDefinitionSource 
    
//~ Static fields/initializers ============================================= 

    
private static final Log logger = LogFactory.getLog(AbstractMethodDefinitionSource.class); 

    
//~ Methods ================================================================ 

    
public ConfigAttributeDefinition getAttributes(Object object) 
        
throws IllegalArgumentException 
        Assert.notNull(object, 
"Object cannot be null"); 

        
if (object instanceof MethodInvocation) 
            
return this.lookupAttributes(((MethodInvocation) object).getMethod()); 
        }
 

        
if (object instanceof JoinPoint) 
            JoinPoint jp 
= (JoinPoint) object; 
            Class targetClazz 
= jp.getTarget().getClass(); 
            String targetMethodName 
= jp.getStaticPart().getSignature().getName(); 
            Class[] types 
= ((CodeSignature) jp.getStaticPart().getSignature()) 
                    .getParameterTypes(); 

            
if (logger.isDebugEnabled()) 
                logger.debug(
"Target Class: " + targetClazz); 
                logger.debug(
"Target Method Name: " + targetMethodName); 

                
for (int i = 0; i < types.length; i++
                    
if (logger.isDebugEnabled()) 
                        logger.debug(
"Target Method Arg #" + i + "" 
                                
+ types[i]); 
                    }
 
                }
 
            }
 

            
try 
                
return this.lookupAttributes(targetClazz.getMethod(targetMethodName, types)); 
            }
 catch (NoSuchMethodException nsme) 
                
throw new IllegalArgumentException("Could not obtain target method from JoinPoint: " + jp); 
            }
 
        }
 

        
throw new IllegalArgumentException("Object must be a MethodInvocation or JoinPoint"); 
    }
 

    
public boolean supports(Class clazz) 
        
return (MethodInvocation.class.isAssignableFrom(clazz) 
        
|| JoinPoint.class.isAssignableFrom(clazz)); 
    }
 


    
protected abstract ConfigAttributeDefinition lookupAttributes(Method method); 
}
 

我们要做的就是实现它的
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 

以下是我的标志实现,大致思路是 根据 页面 的传来的 方法名(即 FunctionName)查询出对应的Functions,并且包装成grantedFunctions ,然后根据用户的角色查询出用户对应的Functions ,再取这两个集合的交集,最后再根据这个集合是否为空判断是否显示标志体的内容。
  1  package  sample.auth; 
  2  import  java.util.Arrays; 
  3  import  java.util.Collection; 
  4  import  java.util.Collections; 
  5  import  java.util.HashSet; 
  6  import  java.util.Iterator; 
  7  import  java.util.List; 
  8  import  java.util.Set; 
  9 
 10  import  javax.servlet.jsp.JspException; 
 11  import  javax.servlet.jsp.tagext.Tag; 
 12  import  javax.servlet.jsp.tagext.TagSupport; 
 13 
 14  import  org.acegisecurity.Authentication; 
 15  import  org.acegisecurity.GrantedAuthority; 
 16  import  org.acegisecurity.context.SecurityContextHolder; 
 17  import  org.springframework.util.StringUtils; 
 18  import  org.springframework.web.util.ExpressionEvaluationUtils; 
 19 
 20  import  sample.web.action.AppContext; 
 21  /**  
 22 
 23  @author  limq 
 24 
 25  */  
 26  public   class  AuthorizeActionTag  extends  TagSupport{ 
 27 
 28               private  String ifAllGranted  =   ""
 29               private  String ifAnyGranted  =   ""
 30               private  String ifNotGranted  =   ""
 31              
 32               public   void  setIfAllGranted(String ifAllGranted)  throws  JspException { 
 33                   this .ifAllGranted  =  ifAllGranted; 
 34              } 
 35 
 36               public  String getIfAllGranted() { 
 37                   return  ifAllGranted; 
 38              } 
 39 
 40               public   void  setIfAnyGranted(String ifAnyGranted)  throws  JspException { 
 41                   this .ifAnyGranted  =  ifAnyGranted; 
 42              } 
 43 
 44               public  String getIfAnyGranted() { 
 45                   return  ifAnyGranted; 
 46              } 
 47 
 48               public   void  setIfNotGranted(String ifNotGranted)  throws  JspException { 
 49                   this .ifNotGranted  =  ifNotGranted; 
 50              } 
 51 
 52               public  String getIfNotGranted() { 
 53                   return  ifNotGranted; 
 54              } 
 55              
 56               public   int  doStartTag()  throws  JspException { 
 57                   if  ((( null   ==  ifAllGranted)  ||   "" .equals(ifAllGranted)) 
 58                       &&  (( null   ==  ifAnyGranted)  ||   "" .equals(ifAnyGranted)) 
 59                       &&  (( null   ==  ifNotGranted)  ||   "" .equals(ifNotGranted))) { 
 60                       return  Tag.SKIP_BODY; 
 61                  } 
 62 
 63                   final  Collection granted  =  getPrincipalFunctionByAuthorities(); 
 64 
 65                   final  String evaledIfNotGranted  =  ExpressionEvaluationUtils 
 66                      .evaluateString( " ifNotGranted " , ifNotGranted, pageContext); 
 67 
 68                   if  (( null   !=  evaledIfNotGranted)  &&   ! "" .equals(evaledIfNotGranted)) { 
 69                      Set grantedCopy  =  retainAll(granted, 
 70                                      parseSecurityString(evaledIfNotGranted)); 
 71 
 72                       if  ( ! grantedCopy.isEmpty()) { 
 73                           return  Tag.SKIP_BODY; 
 74                      } 
 75                  } 
 76 
 77                   final  String evaledIfAllGranted  =  ExpressionEvaluationUtils 
 78                      .evaluateString( " ifAllGranted " , ifAllGranted, pageContext); 
 79 
 80                   if  (( null   !=  evaledIfAllGranted)  &&   ! "" .equals(evaledIfAllGranted)) { 
 81                       if  ( ! granted.containsAll(parseSecurityString(evaledIfAllGranted))) { 
 82                           return  Tag.SKIP_BODY; 
 83                      } 
 84                  } 
 85 
 86                   final  String evaledIfAnyGranted  =  ExpressionEvaluationUtils 
 87                      .evaluateString( " ifAnyGranted " , ifAnyGranted, pageContext); 
 88 
 89                   if  (( null   !=  evaledIfAnyGranted)  &&   ! "" .equals(evaledIfAnyGranted)) { 
 90                      Set grantedCopy  =  retainAll(granted, 
 91                                      parseSecurityString(evaledIfAnyGranted)); 
 92 
 93                       if  (grantedCopy.isEmpty()) { 
 94                           return  Tag.SKIP_BODY; 
 95                      } 
 96                  } 
 97 
 98                   return  Tag.EVAL_BODY_INCLUDE; 
 99              } 
100       /**  
101       * 得到用户的Authentication,并且从Authentication中获得 Authorities,进而得到 授予用户的 Function 
102       *  @return  
103        */  
104               private  Collection getPrincipalFunctionByAuthorities() { 
105                      
106                      
107              Authentication currentUser  =  SecurityContextHolder.getContext() 
108              .getAuthentication(); 
109                   if  ( null   ==  currentUser) { 
110                       return  Collections.EMPTY_LIST; 
111                  } 
112 
113                   if  (( null   ==  currentUser.getAuthorities()) 
114                       ||  (currentUser.getAuthorities().length  <   1 )) { 
115                       return  Collections.EMPTY_LIST; 
116                  } 
117              //  currentUser.getAuthorities() 返回的是 GrantedAuthority[] 
118                  List granted  =  Arrays.asList(currentUser.getAuthorities()); 
119                  AuthDao authDao  = (AuthDao) AppContext.getInstance().getAppContext().getBean( " authDao " ); 
120                  Collection grantedFunctions  =  authDao.getFunctionsByRoles(granted); 
121                   return  grantedFunctions; 
122              } 
123 
124               /**  
125               * 得到用户功能(Function)的集合,并且验证是否合法 
126               *  @param  c Collection 类型 
127               *  @return  Set类型 
128                */  
129               private  Set SecurityObjectToFunctions(Collection c) { 
130                  Set target  =   new  HashSet(); 
131 
132                   for  (Iterator iterator  =  c.iterator(); iterator.hasNext();) { 
133                      GrantedFunction function  =  (GrantedFunction) iterator.next(); 
134 
135                       if  ( null   ==  function.getFunction()) { 
136                           throw   new  IllegalArgumentException( 
137                               " Cannot process GrantedFunction objects which return null from getFunction() - attempting to process  "  
138                               +  function.toString()); 
139                      } 
140 
141                      target.add(function.getFunction()); 
142                  } 
143 
144                   return  target; 
145              } 
146 
147               /**  
148               * 处理页面标志属性 ,用' ,'区分 
149                */  
150               private  Set parseSecurityString(String functionsString) { 
151                   final  Set requiredFunctions  =   new  HashSet(); 
152                   final  String[] functions  =  StringUtils 
153                      .commaDelimitedListToStringArray(functionsString); 
154 
155                   for  ( int  i  =   0 ; i  <  functions.length; i ++ ) { 
156                      String authority  =  functions[i]; 
157 
158                    //  Remove the role's whitespace characters without depending on JDK 1.4+ 
159                    //  Includes space, tab, new line, carriage return and form feed. 
160                   String function  =  StringUtils.replace(authority,  "   " "" ); 
161                   function  =  StringUtils.replace(function,  " /t " "" ); 
162                   function  =  StringUtils.replace(function,  " /r " "" ); 
163                   function  =  StringUtils.replace(function,  " /n " "" ); 
164                   function  =  StringUtils.replace(function,  " /f " "" ); 
165 
166                   requiredFunctions.add( new  GrantedFunctionImpl(function)); 
167                  } 
168 
169                   return  requiredFunctions; 
170              } 
171               /**  
172               * 获得用户所拥有的Function 和 要求的 Function 的交集 
173               *  @param  granted 用户已经获得的Function 
174               *  @param  required 所需要的Function 
175               *  @return  
176                */  
177            
178               private  Set retainAll( final  Collection granted,  final  Set required) { 
179                  Set grantedFunction  =  SecurityObjectToFunctions(granted); 
180                  Set requiredFunction  =  SecurityObjectToFunctions(required); 
181                   //  retailAll() 获得 grantedFunction 和 requiredFunction 的交集 
182                   //  即删除 grantedFunction 中  除了 requiredFunction 的项 
183                  grantedFunction.retainAll(requiredFunction); 
184 
185                   return  rolesToAuthorities(grantedFunction, granted); 
186              } 
187 
188               /**  
189               * 
190               *  @param  grantedFunctions 已经被过滤过的Function            
191               *  @param  granted 未被过滤过的,即用户所拥有的Function 
192               *  @return  
193                */  
194               private  Set rolesToAuthorities(Set grantedFunctions, Collection granted) { 
195                  Set target  =   new  HashSet(); 
196 
197                   for  (Iterator iterator  =  grantedFunctions.iterator(); iterator.hasNext();) { 
198                      String function  =  (String) iterator.next(); 
199 
200                       for  (Iterator grantedIterator  =  granted.iterator(); 
201                          grantedIterator.hasNext();) { 
202                          GrantedFunction grantedFunction  =  (GrantedFunction) grantedIterator 
203                              .next(); 
204 
205                           if  (grantedFunction.getFunction().equals(function)) { 
206                              target.add(grantedFunction); 
207 
208                               break
209                          } 
210                      } 
211                  } 
212 
213                   return  target; 
214              } 
215 
216 
217 
再说明一下吧,通过 AppContext 获得了Spring的上下文,以及AuthDao(实际意义上讲以不再是单纯的Dao,应该是Service)
package  sample.auth; 

import  java.util.Collection; 
public   interface   AuthDao 

    
/** 
     *  根据用户的角色集合 得到 用户的 操作权限 
     * 
@param granted 已授予用户的角色集合 
     * 
@return 操作权限的集合 
     
*/
 
        
public Collection getFunctionsByRoles(Collection granted); 
}
 
以下是AuthDao 的实现

package  sample.auth; 

import  java.util.Collection; 
import  java.util.HashSet; 
import  java.util.Iterator; 
import  java.util.Set; 

import  org.acegisecurity.GrantedAuthority; 

import  sample.auth.cache.FunctionCache; 
import  sample.auth.cache.info.RoleByNameCache; 
import  sample.dao.IBaseDao; 
import  sample.mappings.function.Function; 
import  sample.mappings.role.Role; 


public   class  AuthDaoImpl   implements  AuthDao { 

    
private  IBaseDao baseDao; 
    
private  FunctionCache cache; 
    
private  RoleByNameCache roleCache; 
    
        
public  RoleByNameCache getRoleCache() { 
                
return  roleCache; 
        } 

        
public   void  setRoleCache(RoleByNameCache roleCache) { 
                
this .roleCache  =  roleCache; 
        } 

        
public  FunctionCache getCache() { 
                
return  cache; 
        } 

        
public   void  setCache(FunctionCache cache) { 
                
this .cache  =  cache; 
        } 

        
public  IBaseDao getBaseDao() { 
        
return  baseDao; 
    } 

    
public   void  setBaseDao(IBaseDao baseDao) { 
        
this .baseDao  =  baseDao; 
    } 

  

        
public  Collection getFunctionsByRoles(Collection granted) { 
                Set set 
=   new  HashSet(); 
                
if ( null   ==  granted)  throw   new  IllegalArgumentException( " Granted Roles cannot be null " ); 
        
                
for (Iterator it  =  granted.iterator();it.hasNext();){ 
            
            GrantedAuthority grantedAuthority 
=  (GrantedAuthority)it.next(); 
            Role  role 
=  roleCache.getRoleByRoleNameCache(grantedAuthority.getAuthority());  //  
             if (role  ==   null ){ 
                    role 
=  (Role)baseDao.loadByKey(Role. class " name " , grantedAuthority.getAuthority()); 
                    roleCache.putRoleInCache(role); 
            } 
            GrantedFunction[] grantedFunctions 
=  cache.getFunctionFromCache(role.getName()); 
            
            
if (grantedFunctions  ==   null ){ 
                    
                    Set functions 
=  role.getFunctions(); 
                            
for (Iterator it2  =  functions.iterator();it2.hasNext();){        
                    Function function 
=  (Function)it2.next(); 
                    GrantedFunction grantedFunction 
=   new  GrantedFunctionImpl(function.getName()); 
                                    set.add(  grantedFunction  ); 
                            } 
                  
                            grantedFunctions 
=  (GrantedFunction[]) set.toArray( new  GrantedFunction[ 0 ]); 
                            cache.putFuncitonInCache(role.getName(),grantedFunctions); 
            } 
            
            
for ( int  i  =   0  ; i  <  grantedFunctions.length; i ++ ){ 
                    GrantedFunction grantedFunction 
=  grantedFunctions[i]; 
                    set.add(grantedFunction); 
            } 
                } 
        
                
return  set; 
        } 



3 基于hibernate的用户验证

acegi 默认的 的 用户验证是 通过UserDetailsService 接口 实现的 也就是说我们只要实现了 它的loadUserByUsername 方法。
1 
2  public  UserDetails loadUserByUsername(String username) 
3           throws  UsernameNotFoundException, DataAccessException; 
以下是我的实现
  1  package  sample.auth; 
  2 
  3  import  java.util.ArrayList; 
  4  import  java.util.Iterator; 
  5  import  java.util.List; 
  6  import  java.util.Set; 
  7 
  8  import  org.acegisecurity.GrantedAuthority; 
  9  import  org.acegisecurity.GrantedAuthorityImpl; 
 10  import  org.acegisecurity.userdetails.User; 
 11  import  org.acegisecurity.userdetails.UserDetails; 
 12  import  org.acegisecurity.userdetails.UserDetailsService; 
 13  import  org.acegisecurity.userdetails.UsernameNotFoundException; 
 14  import  org.springframework.dao.DataAccessException; 
 15 
 16  import  sample.auth.cache.AuthorityBasedUserCache; 
 17  import  sample.dao.IBaseDao; 
 18  import  sample.mappings.role.Role; 
 19  import  sample.utils.MisUtils; 
 20 
 21  public   class  HibernateDaoImpl  implements  UserDetailsService{ 
 22 
 23          
 24           private  String rolePrefix  =   ""
 25           private   boolean  usernameBasedPrimaryKey  =   false
 26       private  AuthorityBasedUserCache cache; 
 27 
 28       private  IBaseDao baseDao; 
 29 
 30           public  String getRolePrefix() { 
 31                   return  rolePrefix; 
 32          } 
 33          
 34           public   void  setRolePrefix(String rolePrefix) { 
 35                   this .rolePrefix  =  rolePrefix; 
 36          } 
 37          
 38           public  UserDetails loadUserByUsername(String username)  throws  UsernameNotFoundException, DataAccessException { 
 39                  UserDetails user  =  getUsersByUsernameQuery(username); 
 40                   if (user  ==   null return   null
 41                  
 42                  GrantedAuthority[] arrayAuths  = getAuthoritiesByUsernameQuery(username); 
 43                if  (arrayAuths.length  ==   0 ) { 
 44                       throw   new  UsernameNotFoundException( " User has no GrantedAuthority " ); 
 45                  } 
 46                
 47                return   new  User(username, user.getPassword(), user.isEnabled(), 
 48                        true true true , arrayAuths); 
 49          } 
 50 
 51           /**  
 52          * 根据用户名查找用户 
 53          *  @param  username 
 54          *  @return  
 55          *  @throws  DataAccessException 
 56           */  
 57           public  UserDetails getUsersByUsernameQuery(String username) throws  DataAccessException { 
 58                          sample.mappings.user.User misUser  =  (sample.mappings.user.User)baseDao.loadByKey(sample.mappings.user.User. class , " name " ,username); 
 59                           if (misUser  !=   null
 60                          { 
 61                          org.acegisecurity.userdetails.UserDetails user  =  
 62                           new  User(misUser.getName(),misUser.getPassword(),MisUtils.parseBoolean(misUser.getEnable()), true , true , true ,getAuthoritiesByUsernameQuery(username)); 
 63                           return  user; 
 64                          } else  
 65                           return   null ;        
 66                  } 
 67          
 68           /**  
 69            * 根据用户名查找角色 
 70            *  @param  username 
 71            *  @return  GrantedAuthority[] 用户角色 
 72            *  @throws  DataAccessException 
 73             */  
 74           public  GrantedAuthority[] getAuthoritiesByUsernameQuery(String username) 
 75                   throws  DataAccessException { 
 76                  sample.mappings.user.User misUser 
 77                   =  (sample.mappings.user.User)baseDao.loadByKey(sample.mappings.user.User. class , " name " ,username); 
 78 
 79           if (misUser  !=   null ){ 
 80                  GrantedAuthority[] grantedAuthoritys  =  cache.getAuthorityFromCache(misUser.getName()); 
 81          
 82                   if (grantedAuthoritys  ==   null ){ 
 83                  
 84                          Set roles  =      misUser.getRoles(); 
 85                          Iterator it  =  roles.iterator(); 
 86                  
 87                          List list  =   new  ArrayList(); 
 88                           while (it.hasNext() ){ 
 89          
 90                                  GrantedAuthorityImpl gai  =   new  GrantedAuthorityImpl(  ((Role)it.next()).getName()  ); 
 91                                  list.add(gai); 
 92                                  } 
 93                          grantedAuthoritys  = (GrantedAuthority[]) list.toArray( new   GrantedAuthority[ 0 ]); 
 94                          cache.putAuthorityInCache(misUser.getName(),grantedAuthoritys); 
 95                           return  grantedAuthoritys; 
 96                  
 97                  } 
 98                  return  grantedAuthoritys; 
 99          } 
100 
101                   return   null
102 
103 
104           public  IBaseDao getBaseDao() { 
105                   return  baseDao; 
106          } 
107 
108           public   void  setBaseDao(IBaseDao baseDao) { 
109                   this .baseDao  =  baseDao; 
110          } 
111 
112           public  AuthorityBasedUserCache getCache() { 
113                   return  cache; 
114          } 
115 
116           public   void  setCache(AuthorityBasedUserCache cache) { 
117                   this .cache  =  cache; 
118          } 
119 
120 

    最近在做项目遇到了权限管理,用户要求可以自己建立不同的角色对系统的资源进行控制, 不同的用户有不同的角色,又恰恰框架中用到了struts+spring+hibernate,要求在web层调用 业务逻辑层 时不考虑权限,web层可以控制用户的显示界面,逻辑层处理用户权限问题。
想来想去好像只有spring 的aop 可以做到,在调用到 接口 中的方法时,首先检查用户的权限,如果检查通过则继续执行,否则抛出异常。但是新的问题又出现了,如何在逻辑层上来得到当前用户的id,以致用户的 角色,总不能每次都要从web中传来一个 httprequest,或者 session 这类的吧。在网上看了很多资料,发现了acegi,恰好解决了以上的难题,具体的实现原理这里就不多说了,网上有很多相关资料。
说正题,首先来看看acegi 的官方 example ,我下载的是acegi-security-1.0.0-RC1,解压缩后可以看到acegi-security-sample-contacts-filter.war,打开配置文件有这样几句

 1     < bean  id ="contactManagerSecurity"  class ="org.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor" >  
 2         < property  name ="authenticationManager" >< ref  bean ="authenticationManager" /></ property >  
 3         < property  name ="accessDecisionManager" >< ref  local ="businessAccessDecisionManager" /></ property >  
 4         < property  name ="afterInvocationManager" >< ref  local ="afterInvocationManager" /></ property >  
 5         < property  name ="objectDefinitionSource" >  
 6            < value >  
 7              sample.contact.ContactManager.create=ROLE_USER 
 8              sample.contact.ContactManager.getAllRecipients=ROLE_USER 
 9              sample.contact.ContactManager.getAll=ROLE_USER,AFTER_ACL_COLLECTION_READ 
10              sample.contact.ContactManager.getById=ROLE_USER,AFTER_ACL_READ 
11              sample.contact.ContactManager.delete=ACL_CONTACT_DELETE 
12              sample.contact.ContactManager.deletePermission=ACL_CONTACT_ADMIN 
13              sample.contact.ContactManager.addPermission=ACL_CONTACT_ADMIN 
14            </ value >  
15         </ property >  
16      </ bean >  
17 
 
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值