szhswl
          宋針還的個(gè)人空間
          轉(zhuǎn)自:http://www.cublog.cn/u/11905/showart_162625.html

          最近在做項(xiàng)目遇到了權(quán)限管理,用戶要求可以自己建立不同的角色對系統(tǒng)的資源進(jìn)行控制, 不同的用戶有不同的角色,又恰恰框架中用到了struts+spring+hibernate,要求在web層調(diào)用 業(yè)務(wù)邏輯層 時(shí)不考慮權(quán)限,web層可以控制用戶的顯示界面,邏輯層處理用戶權(quán)限問題。
          想來想去好像只有spring 的aop 可以做到,在調(diào)用到 接口 中的方法時(shí),首先檢查用戶的權(quán)限,如果檢查通過則繼續(xù)執(zhí)行,否則拋出異常。但是新的問題又出現(xiàn)了,如何在邏輯層上來得到當(dāng)前用戶的id,以致用戶的 角色,總不能每次都要從web中傳來一個(gè) httprequest,或者 session 這類的吧。在網(wǎng)上看了很多資料,發(fā)現(xiàn)了acegi,恰好解決了以上的難題,具體的實(shí)現(xiàn)原理這里就不多說了,網(wǎng)上有很多相關(guān)資料。
          說正題,首先來看看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 

          可以看到它是通過讀配置文件來判斷執(zhí)行某個(gè)方法所需要的角色的,再看這幾句
          <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> 
          同樣是將頁面的訪問權(quán)限寫死在配置文件中,再來看看它的tag是如何處理的
          <auth:authorize ifAnyGranted="ROLE_DELETE"> 
                    
          <href="">刪除</a> 
          </auth:authorize> 
          可見它是要求我們對鏈接或者其他資源的保護(hù)時(shí)提供 用戶角色,可是既然角色是用戶自己添加的我們又如何來寫死在這里呢?
          還有就是它對用戶驗(yàn)證默認(rèn)使用的是jdbc,即 JdbcDaoImpl
          <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> 
                          
          <property name="dataSource"><ref local="dataSource"/></property> 
                  
          </bean> 
          而我們希望基于Hibernate的Dao來實(shí)現(xiàn)。
          可見僅僅使用現(xiàn)有的acegi 是 無法滿足我們項(xiàng)目開發(fā)的需求的。
          解決方法:

          1: 開發(fā)基于數(shù)據(jù)庫的保護(hù)資源。

          看過acegi的源代碼就會知道,對保護(hù)資源的定義是通過實(shí)現(xiàn)ObjectDefinitionSource這個(gè)接口來實(shí)現(xiàn)的,而且acegi為我們提供了默認(rèn)實(shí)現(xiàn)的抽象類
          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); 
          }
           

          我們要做的就是實(shí)現(xiàn)它的
          protected abstract ConfigAttributeDefinition lookupAttributes(Method method);方法,
          以下是我的實(shí)現(xiàn)方法,大致思路是這樣,通過由抽象類傳來的Method 對象得到
          調(diào)用這個(gè)方法的 包名,類名,方法名 也就是secureObjectName, 查詢數(shù)據(jù)庫并將結(jié)果映射為Function 也就是secureObject ,由于Function 與 Role 的多對多關(guān)系 可以得到 Function所對應(yīng)的 Roles ,在將role 包裝成GrantedAuthority (也就是acegi中的角色)。其中由于頻繁的對數(shù)據(jù)庫的查詢 所以使用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對數(shù)據(jù)庫操作的實(shí)現(xiàn) 
           28         private IBaseDao baseDao; 
           29         // AuthorityBasedFunctionCache 通過Function 查 Role 時(shí)緩存 
           30         private AuthorityBasedFunctionCache cache; 
           31         // FunctionByNameCache 由反射到的方法名查找 數(shù)據(jù)庫對應(yīng)的Function 時(shí)的緩存 
           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 為數(shù)據(jù)庫中保護(hù)資源的映射 
           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:定義 基于方法的 自定義標(biāo)志

          通過以上的分析 , 要想使用acegi 做頁面的顯示控制僅僅靠角色(Role)是不行的,因?yàn)橛脩艨赡茈S時(shí)定義出新的角色,所以只能 基于方法(Function)的控制。可是acegi 只是提供了基于 角色的 接口GrantedAuthority ,怎么辦?  ,如法炮制。 首先定義出我們自己的GrantedFunction,實(shí)現(xiàn)也雷同 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 

          以下是我的標(biāo)志實(shí)現(xiàn),大致思路是 根據(jù) 頁面 的傳來的 方法名(即 FunctionName)查詢出對應(yīng)的Functions,并且包裝成grantedFunctions ,然后根據(jù)用戶的角色查詢出用戶對應(yīng)的Functions ,再取這兩個(gè)集合的交集,最后再根據(jù)這個(gè)集合是否為空判斷是否顯示標(biāo)志體的內(nèi)容。
            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,進(jìn)而得到 授予用戶的 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)的集合,并且驗(yàn)證是否合法 
          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              * 處理頁面標(biāo)志屬性 ,用' ,'區(qū)分 
          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 用戶已經(jīng)獲得的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 的項(xiàng) 
          183                 grantedFunction.retainAll(requiredFunction); 
          184 
          185                 return rolesToAuthorities(grantedFunction, granted); 
          186             } 
          187 
          188             /** 
          189              * 
          190              * @param grantedFunctions 已經(jīng)被過濾過的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(實(shí)際意義上講以不再是單純的Dao,應(yīng)該是Service)
          package sample.auth; 

          import java.util.Collection; 
          public interface  AuthDao 

              
          /** 
               *  根據(jù)用戶的角色集合 得到 用戶的 操作權(quán)限 
               * 
          @param granted 已授予用戶的角色集合 
               * 
          @return 操作權(quán)限的集合 
               
          */
           
                  
          public Collection getFunctionsByRoles(Collection granted); 
          }
           
          以下是AuthDao 的實(shí)現(xiàn)

          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的用戶驗(yàn)證

          acegi 默認(rèn)的 的 用戶驗(yàn)證是 通過UserDetailsService 接口 實(shí)現(xiàn)的 也就是說我們只要實(shí)現(xiàn)了 它的loadUserByUsername 方法。
          1 
          2 public UserDetails loadUserByUsername(String username) 
          3         throws UsernameNotFoundException, DataAccessException; 
          以下是我的實(shí)現(xiàn)
            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 == nullreturn 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                      truetruetrue, arrayAuths); 
           49         } 
           50 
           51         /** 
           52         * 根據(jù)用戶名查找用戶 
           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           * 根據(jù)用戶名查找角色 
           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 
          121 
          通過以上對acegi 的 處理,足以滿足我們目前在spring下基于RBAC的動態(tài)權(quán)限管理。同時(shí)在對頻繁的數(shù)據(jù)庫查詢上使用了Ehcache作為緩存,在性能上有了很大的改善。


          ---------------------------------------------------------------------------------------------------------------------------------
          說人之短,乃護(hù)己之短。夸己之長,乃忌人之長。皆由存心不厚,識量太狹耳。能去此弊,可以進(jìn)德,可以遠(yuǎn)怨。
          http://www.aygfsteel.com/szhswl
          ------------------------------------------------------------------------------------------------------ ----------------- ---------
          posted on 2007-12-03 20:37 宋針還 閱讀(309) 評論(0)  編輯  收藏 所屬分類: JAVA
          主站蜘蛛池模板: 高碑店市| 临泉县| 凤阳县| 灵璧县| 柞水县| 阳西县| 游戏| 丽水市| 兴宁市| 那曲县| 荥经县| 铜陵市| 息烽县| 大悟县| 海宁市| 朔州市| 五家渠市| 武穴市| 隆林| 乐山市| 寻甸| 应城市| 格尔木市| 靖州| 鄂州市| 岳普湖县| 台北市| 淅川县| 大宁县| 朝阳市| 广宁县| 阿瓦提县| 寻甸| 讷河市| 如东县| 五大连池市| 贵溪市| 隆尧县| 宁海县| 清水河县| 乳源|