隨筆 - 13  文章 - 47  trackbacks - 0
          <2006年12月>
          262728293012
          3456789
          10111213141516
          17181920212223
          24252627282930
          31123456

          常用鏈接

          留言簿(4)

          隨筆分類

          隨筆檔案

          收藏夾

          個人博客

          參考文檔

          搜索

          •  

          最新評論

          閱讀排行榜

          評論排行榜

          轉(zhuǎn)自:http://www.cublog.cn/u/11905/showart_162625.html

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

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

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

          我們要做的就是實現(xiàn)它的
          protected abstract ConfigAttributeDefinition lookupAttributes(Method method);方法,
          以下是我的實現(xiàn)方法,大致思路是這樣,通過由抽象類傳來的Method 對象得到
          調(diào)用這個方法的 包名,類名,方法名 也就是secureObjectName, 查詢數(shù)據(jù)庫并將結(jié)果映射為Function 也就是secureObject ,由于Function 與 Role 的多對多關(guān)系 可以得到 Function所對應的 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ù)庫操作的實現(xiàn)?
          ?28?????????private?IBaseDao?baseDao;?
          ?29?????????//?AuthorityBasedFunctionCache?通過Function?查?Role?時緩存?
          ?30?????????private?AuthorityBasedFunctionCache?cache;?
          ?31?????????//?FunctionByNameCache?由反射到的方法名查找?數(shù)據(jù)庫對應的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?為數(shù)據(jù)庫中保護資源的映射?
          ?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,實現(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?

          以下是我的標志實現(xiàn),大致思路是 根據(jù) 頁面 的傳來的 方法名(即 FunctionName)查詢出對應的Functions,并且包裝成grantedFunctions ,然后根據(jù)用戶的角色查詢出用戶對應的Functions ,再取這兩個集合的交集,最后再根據(jù)這個集合是否為空判斷是否顯示標志體的內(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,進而得到?授予用戶的?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??????????????*?處理頁面標志屬性?,用'?,'區(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?的項?
          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(實際意義上講以不再是單純的Dao,應該是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 的實現(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的用戶驗證

          acegi 默認的 的 用戶驗證是 通過UserDetailsService 接口 實現(xiàn)的 也就是說我們只要實現(xiàn)了 它的loadUserByUsername 方法。
          1?
          2?public?UserDetails?loadUserByUsername(String?username)?
          3?????????throws?UsernameNotFoundException,?DataAccessException;?
          以下是我的實現(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?==?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?????????*?根據(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ù)據(jù)庫查詢上使用了Ehcache作為緩存,在性能上有了很大的改善。
          posted on 2006-12-03 16:04 西紅柿(tomato) 閱讀(1565) 評論(1)  編輯  收藏 所屬分類: 安全認證相關(guān)

          FeedBack:
          # re: Acegi+hibernate 動態(tài)實現(xiàn)基于角色的權(quán)限管理 2006-12-14 12:18 信天翁
          太好了!  回復  更多評論
            
          主站蜘蛛池模板: 崇州市| 桑植县| 江城| 裕民县| 阿坝| 龙岩市| 宜黄县| 汉阴县| 中卫市| 贡嘎县| 剑川县| 景洪市| 湘乡市| 茶陵县| 涡阳县| 烟台市| 信丰县| 古浪县| 广宁县| 云林县| 玉田县| 民权县| 克什克腾旗| 溧水县| 荣昌县| 乐亭县| 嘉兴市| 曲水县| 孟村| 仪征市| 丰顺县| 茶陵县| 册亨县| 兴业县| 德江县| 邵东县| 赤壁市| 宜昌市| 隆昌县| 抚州市| 新巴尔虎右旗|