首先来看看acegi 的官方 example ,我下载的是acegi-security-1.0.0-RC1,解压缩后可以看到acegi-security-sample-contacts-filter.war,打开配置文件有这样几句
可以看到它是通过读配置文件来判断执行某个方法所需要的角色的,再看这几句
同样是将页面的访问权限写死在配置文件中,再来看看它的tag是如何处理的
可见它是要求我们对链接或者其他资源的保护时提供 用户角色,可是既然角色是用户自己添加的我们又如何来写死在这里呢?
还有就是它对用户验证默认使用的是jdbc,即 JdbcDaoImpl
而我们希望基于Hibernate的Dao来实现。
可见仅仅使用现有的acegi 是 无法满足我们项目开发的需求的。
解决方法:
1: 开发基于数据库的保护资源。
看过acegi的源代码就会知道,对保护资源的定义是通过实现ObjectDefinitionSource这个接口来实现的,而且acegi为我们提供了默认实现的抽象类
我们要做的就是实现它的
protected abstract ConfigAttributeDefinition lookupAttributes(Method method);方法,
以下是我的实现方法,大致思路是这样,通过由抽象类传来的Method 对象得到
调用这个方法的 包名,类名,方法名 也就是secureObjectName, 查询数据库并将结果映射为Function 也就是secureObject ,由于Function 与 Role 的多对多关系 可以得到 Function所对应的 Roles ,在将role 包装成GrantedAuthority (也就是acegi中的角色)。其中由于频繁的对数据库的查询 所以使用Ehcache 来作为缓存。
2:定义 基于方法的 自定义标志
通过以上的分析 , 要想使用acegi 做页面的显示控制仅仅靠角色(Role)是不行的,因为用户可能随时定义出新的角色,所以只能 基于方法(Function)的控制。可是acegi 只是提供了基于 角色的 接口GrantedAuthority ,怎么办? ,如法炮制。 首先定义出我们自己的GrantedFunction,实现也雷同 GrantedAuthorityImpl
以下是我的标志实现,大致思路是 根据 页面 的传来的 方法名(即 FunctionName)查询出对应的Functions,并且包装成grantedFunctions ,然后根据用户的角色查询出用户对应的Functions ,再取这两个集合的交集,最后再根据这个集合是否为空判断是否显示标志体的内容。
再说明一下吧,通过 AppContext 获得了Spring的上下文,以及AuthDao(实际意义上讲以不再是单纯的Dao,应该是Service)
以下是AuthDao 的实现
3 基于hibernate的用户验证
acegi 默认的 的 用户验证是 通过UserDetailsService 接口 实现的 也就是说我们只要实现了 它的loadUserByUsername 方法。
以下是我的实现
java代码: |
<bean id="contactManagerSecurity" class="org. acegisecurity. intercept. method. aopalliance. MethodSecurityInterceptor"> <property name="authenticationManager"><ref bean="authenticationManager"/></property> <property name="accessDecisionManager"><ref local="businessAccessDecisionManager"/></property> <property name="afterInvocationManager"><ref local="afterInvocationManager"/></property> <property name="objectDefinitionSource"> <value> sample. contact. ContactManager. create=ROLE_USER sample. contact. ContactManager. getAllRecipients=ROLE_USER sample. contact. ContactManager. getAll=ROLE_USER,AFTER_ACL_COLLECTION_READ sample. contact. ContactManager. getById=ROLE_USER,AFTER_ACL_READ sample. contact. ContactManager. delete=ACL_CONTACT_DELETE sample. contact. ContactManager. deletePermission=ACL_CONTACT_ADMIN sample. contact. ContactManager. addPermission=ACL_CONTACT_ADMIN </value> </property> </bean> |
可以看到它是通过读配置文件来判断执行某个方法所需要的角色的,再看这几句
java代码: |
<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是如何处理的
java代码: |
<auth:authorize ifAnyGranted="ROLE_DELETE"> <a href="">删除</a> </auth:authorize> |
可见它是要求我们对链接或者其他资源的保护时提供 用户角色,可是既然角色是用户自己添加的我们又如何来写死在这里呢?
还有就是它对用户验证默认使用的是jdbc,即 JdbcDaoImpl
java代码: |
<bean id="transactionManager" class="org. springframework. jdbc. datasource. DataSourceTransactionManager"> <property name="dataSource"><ref local="dataSource"/></property> </bean> |
而我们希望基于Hibernate的Dao来实现。
可见仅仅使用现有的acegi 是 无法满足我们项目开发的需求的。
解决方法:
1: 开发基于数据库的保护资源。
看过acegi的源代码就会知道,对保护资源的定义是通过实现ObjectDefinitionSource这个接口来实现的,而且acegi为我们提供了默认实现的抽象类
java代码: |
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 来作为缓存。
java代码: |
package sample. auth; import java. lang. reflect. Method; import java. util. ArrayList; import java. util. Arrays; import java. util. Collection; import java. util. Iterator; import java. util. List; import java. util. Set; import org. acegisecurity. ConfigAttributeDefinition; import org. acegisecurity. ConfigAttributeEditor; import org. acegisecurity. GrantedAuthority; import org. acegisecurity. GrantedAuthorityImpl; import org. acegisecurity. intercept. method. AbstractMethodDefinitionSource; import org. springframework. util. Assert; import sample. auth. cache. AuthorityBasedFunctionCache; import sample. auth. cache. info. FunctionByNameCache; import sample. dao. IBaseDao; import sample. mappings. function. Function; import sample. mappings. role. Role; public class DatabaseDrivenMethodDefinitionSourcew extends AbstractMethodDefinitionSource { // baseDao 提供通过HIbenate对数据库操作的实现 private IBaseDao baseDao; // AuthorityBasedFunctionCache 通过Function 查 Role 时缓存 private AuthorityBasedFunctionCache cache; // FunctionByNameCache 由反射到的方法名查找 数据库对应的Function 时的缓存 private FunctionByNameCache functionCache; public FunctionByNameCache getFunctionCache ( ) { return functionCache; } public void setFunctionCache (FunctionByNameCache functionCache ) { this. functionCache = functionCache; } protected ConfigAttributeDefinition lookupAttributes ( Method mi ) { Assert. notNull (mi,"lookupAttrubutes in the DatabaseDrivenMethodDefinitionSourcew is null" ); String secureObjectName=mi. getDeclaringClass ( ). getName ( ) +"."+ mi. getName ( ); //Function 为数据库中保护资源的映射 Function secureObject=functionCache. getFunctionByCache (secureObjectName ); if (secureObject== null ) //if secure object not exist in database { secureObject= (Function )baseDao. loadByKey (Function. class, "protectfunction", secureObjectName ); functionCache. putFunctionInCache (secureObject ); } if (secureObject== null ) Assert. notNull (secureObject,"secureObject (Function ) not found in db" ); //retrieving roles associated with this secure object Collection roles = null; GrantedAuthority [ ] grantedAuthoritys = cache. getAuthorityFromCache (secureObject. getName ( ) ); // 如果是第一次 cache 为空 if (grantedAuthoritys == null ) { Set rolesSet = secureObject. getRoles ( ); Iterator it = rolesSet. iterator ( ); List list = new ArrayList ( ); while (it. hasNext ( ) ) { Role role = (Role )it. next ( ); GrantedAuthority g = new GrantedAuthorityImpl (role. getName ( ) ); list. add (g ); } grantedAuthoritys = (GrantedAuthority [ ] )list. toArray ( new GrantedAuthority [ 0 ] ); cache. putAuthorityInCache (secureObject. getName ( ),grantedAuthoritys ); roles = Arrays. asList (grantedAuthoritys ); } else { roles = Arrays. asList (grantedAuthoritys ); } if (!roles. isEmpty ( ) ) { ConfigAttributeEditor configAttrEditor= new ConfigAttributeEditor ( ); StringBuffer rolesStr= new StringBuffer ( ); for ( Iterator it = roles. iterator ( );it. hasNext ( ); ) { GrantedAuthority role= (GrantedAuthority )it. next ( ); rolesStr. append (role. getAuthority ( ) ). append ("," ); } configAttrEditor. setAsText ( rolesStr. toString ( ). substring ( 0,rolesStr. length ( )- 1 ) ); ConfigAttributeDefinition configAttrDef= (ConfigAttributeDefinition )configAttrEditor. getValue ( ); return configAttrDef; } Assert. notEmpty (roles,"collection of roles is null or empty" ); return null; } public Iterator getConfigAttributeDefinitions ( ) { return null; } public IBaseDao getBaseDao ( ) { return baseDao; } public void setBaseDao (IBaseDao baseDao ) { this. baseDao = baseDao; } public AuthorityBasedFunctionCache getCache ( ) { return cache; } public void setCache (AuthorityBasedFunctionCache cache ) { this. cache = cache; } } |
2:定义 基于方法的 自定义标志
通过以上的分析 , 要想使用acegi 做页面的显示控制仅仅靠角色(Role)是不行的,因为用户可能随时定义出新的角色,所以只能 基于方法(Function)的控制。可是acegi 只是提供了基于 角色的 接口GrantedAuthority ,怎么办? ,如法炮制。 首先定义出我们自己的GrantedFunction,实现也雷同 GrantedAuthorityImpl
java代码: |
package sample. auth; import java. io. Serializable; public class GrantedFunctionImpl implements GrantedFunction , Serializable { private String function; //~ Constructors =========================================================== public GrantedFunctionImpl ( String function ) { super ( ); this. function = function; } protected GrantedFunctionImpl ( ) { throw new IllegalArgumentException ("Cannot use default constructor" ); } //~ Methods ================================================================ public String getFunction ( ) { return this. function; } public boolean equals ( Object obj ) { if (obj instanceof String ) { return obj. equals (this. function ); } if (obj instanceof GrantedFunction ) { GrantedFunction attr = (GrantedFunction ) obj; return this. function. equals (attr. getFunction ( ) ); } return false; } public int hashCode ( ) { return this. function. hashCode ( ); } public String toString ( ) { return this. function; } } |
以下是我的标志实现,大致思路是 根据 页面 的传来的 方法名(即 FunctionName)查询出对应的Functions,并且包装成grantedFunctions ,然后根据用户的角色查询出用户对应的Functions ,再取这两个集合的交集,最后再根据这个集合是否为空判断是否显示标志体的内容。
java代码: |
package sample. auth; import java. util. Arrays; import java. util. Collection; import java. util. Collections; import java. util. HashSet; import java. util. Iterator; import java. util. List; import java. util. Set; import javax. servlet. jsp. JspException; import javax. servlet. jsp. tagext. Tag; import javax. servlet. jsp. tagext. TagSupport; import org. acegisecurity. Authentication; import org. acegisecurity. GrantedAuthority; import org. acegisecurity. context. SecurityContextHolder; import org. springframework. util. StringUtils; import org. springframework. web. util. ExpressionEvaluationUtils; import sample. web. action. AppContext; /** * * @author limq * */ public class AuthorizeActionTag extends TagSupport { private String ifAllGranted = ""; private String ifAnyGranted = ""; private String ifNotGranted = ""; public void setIfAllGranted ( String ifAllGranted ) throws JspException { this. ifAllGranted = ifAllGranted; } public String getIfAllGranted ( ) { return ifAllGranted; } public void setIfAnyGranted ( String ifAnyGranted ) throws JspException { this. ifAnyGranted = ifAnyGranted; } public String getIfAnyGranted ( ) { return ifAnyGranted; } public void setIfNotGranted ( String ifNotGranted ) throws JspException { this. ifNotGranted = ifNotGranted; } public String getIfNotGranted ( ) { return ifNotGranted; } public int doStartTag ( ) throws JspException { if ( ( ( null == ifAllGranted ) || "". equals (ifAllGranted ) ) && ( ( null == ifAnyGranted ) || "". equals (ifAnyGranted ) ) && ( ( null == ifNotGranted ) || "". equals (ifNotGranted ) ) ) { return Tag. SKIP_BODY; } final Collection granted = getPrincipalFunctionByAuthorities ( ); final String evaledIfNotGranted = ExpressionEvaluationUtils . evaluateString ("ifNotGranted", ifNotGranted, pageContext ); if ( ( null != evaledIfNotGranted ) && !"". equals (evaledIfNotGranted ) ) { Set grantedCopy = retainAll (granted, parseSecurityString (evaledIfNotGranted ) ); if (!grantedCopy. isEmpty ( ) ) { return Tag. SKIP_BODY; } } final String evaledIfAllGranted = ExpressionEvaluationUtils . evaluateString ("ifAllGranted", ifAllGranted, pageContext ); if ( ( null != evaledIfAllGranted ) && !"". equals (evaledIfAllGranted ) ) { if (!granted. containsAll (parseSecurityString (evaledIfAllGranted ) ) ) { return Tag. SKIP_BODY; } } final String evaledIfAnyGranted = ExpressionEvaluationUtils . evaluateString ("ifAnyGranted", ifAnyGranted, pageContext ); if ( ( null != evaledIfAnyGranted ) && !"". equals (evaledIfAnyGranted ) ) { Set grantedCopy = retainAll (granted, parseSecurityString (evaledIfAnyGranted ) ); if (grantedCopy. isEmpty ( ) ) { return Tag. SKIP_BODY; } } return Tag. EVAL_BODY_INCLUDE; } /** * 得到用户的Authentication,并且从Authentication中获得 Authorities,进而得到 授予用户的 Function * @return */ private Collection getPrincipalFunctionByAuthorities ( ) { Authentication currentUser = SecurityContextHolder. getContext ( ) . getAuthentication ( ); if ( null == currentUser ) { return Collections. EMPTY_LIST; } if ( ( null == currentUser. getAuthorities ( ) ) || (currentUser. getAuthorities ( ). length < 1 ) ) { return Collections. EMPTY_LIST; } // currentUser.getAuthorities() 返回的是 GrantedAuthority[] List granted = Arrays. asList (currentUser. getAuthorities ( ) ); AuthDao authDao = (AuthDao ) AppContext. getInstance ( ). getAppContext ( ). getBean ("authDao" ); Collection grantedFunctions = authDao. getFunctionsByRoles (granted ); return grantedFunctions; } /** * 得到用户功能(Function)的集合,并且验证是否合法 * @param c Collection 类型 * @return Set类型 */ private Set SecurityObjectToFunctions ( Collection c ) { Set target = new HashSet ( ); for ( Iterator iterator = c. iterator ( ); iterator. hasNext ( ); ) { GrantedFunction function = (GrantedFunction ) iterator. next ( ); if ( null == function. getFunction ( ) ) { throw new IllegalArgumentException ( "Cannot process GrantedFunction objects which return null from getFunction ( ) - attempting to process " + function. toString ( ) ); } target. add (function. getFunction ( ) ); } return target; } /** * 处理页面标志属性 ,用' ,'区分 */ private Set parseSecurityString ( String functionsString ) { final Set requiredFunctions = new HashSet ( ); final String [ ] functions = StringUtils . commaDelimitedListToStringArray (functionsString ); for ( int i = 0; i < functions. length; i++ ) { String authority = functions [i ]; // Remove the role's whitespace characters without depending on JDK 1.4+ // Includes space, tab, new line, carriage return and form feed. String function = StringUtils. replace (authority, " ", "" ); function = StringUtils. replace (function, "/t", "" ); function = StringUtils. replace (function, "/r", "" ); function = StringUtils. replace (function, "/n", "" ); function = StringUtils. replace (function, "/f", "" ); requiredFunctions. add ( new GrantedFunctionImpl (function ) ); } return requiredFunctions; } /** * 获得用户所拥有的Function 和 要求的 Function 的交集 * @param granted 用户已经获得的Function * @param required 所需要的Function * @return */ private Set retainAll ( final Collection granted, final Set required ) { Set grantedFunction = SecurityObjectToFunctions (granted ); Set requiredFunction = SecurityObjectToFunctions (required ); // retailAll() 获得 grantedFunction 和 requiredFunction 的交集 // 即删除 grantedFunction 中 除了 requiredFunction 的项 grantedFunction. retainAll (requiredFunction ); return rolesToAuthorities (grantedFunction, granted ); } /** * * @param grantedFunctions 已经被过滤过的Function * @param granted 未被过滤过的,即用户所拥有的Function * @return */ private Set rolesToAuthorities ( Set grantedFunctions, Collection granted ) { Set target = new HashSet ( ); for ( Iterator iterator = grantedFunctions. iterator ( ); iterator. hasNext ( ); ) { String function = ( String ) iterator. next ( ); for ( Iterator grantedIterator = granted. iterator ( ); grantedIterator. hasNext ( ); ) { GrantedFunction grantedFunction = (GrantedFunction ) grantedIterator . next ( ); if (grantedFunction. getFunction ( ). equals (function ) ) { target. add (grantedFunction ); break; } } } return target; } } |
再说明一下吧,通过 AppContext 获得了Spring的上下文,以及AuthDao(实际意义上讲以不再是单纯的Dao,应该是Service)
java代码: |
package sample. auth; import java. util. Collection; public interface AuthDao { /** * 根据用户的角色集合 得到 用户的 操作权限 * @param granted 已授予用户的角色集合 * @return 操作权限的集合 */ public Collection getFunctionsByRoles ( Collection granted ); } |
以下是AuthDao 的实现
java代码: |
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 方法。
java代码: |
public UserDetails loadUserByUsername ( String username ) throws UsernameNotFoundException, DataAccessException; |
以下是我的实现
java代码: |
package sample. auth; import java. util. ArrayList; import java. util. Iterator; import java. util. List; import java. util. Set; import org. acegisecurity. GrantedAuthority; import org. acegisecurity. GrantedAuthorityImpl; import org. acegisecurity. userdetails. User; import org. acegisecurity. userdetails. UserDetails; import org. acegisecurity. userdetails. UserDetailsService; import org. acegisecurity. userdetails. UsernameNotFoundException; import org. springframework. dao. DataAccessException; import sample. auth. cache. AuthorityBasedUserCache; import sample. dao. IBaseDao; import sample. mappings. role. Role; import sample. utils. MisUtils; public class HibernateDaoImpl implements UserDetailsService { private String rolePrefix = ""; private boolean usernameBasedPrimaryKey = false; private AuthorityBasedUserCache cache; private IBaseDao baseDao; public String getRolePrefix ( ) { return rolePrefix; } public void setRolePrefix ( String rolePrefix ) { this. rolePrefix = rolePrefix; } public UserDetails loadUserByUsername ( String username ) throws UsernameNotFoundException, DataAccessException { UserDetails user = getUsersByUsernameQuery (username ); if (user == null ) return null; GrantedAuthority [ ] arrayAuths =getAuthoritiesByUsernameQuery (username ); if (arrayAuths. length == 0 ) { throw new UsernameNotFoundException ("User has no GrantedAuthority" ); } return new User (username, user. getPassword ( ), user. isEnabled ( ), true, true, true, arrayAuths ); } /** * 根据用户名查找用户 * @param username * @return * @throws DataAccessException */ public UserDetails getUsersByUsernameQuery ( String username ) throws DataAccessException { sample. mappings. user. User misUser = (sample. mappings. user. User )baseDao. loadByKey (sample. mappings. user. User. class,"name",username ); if (misUser != null ) { org. acegisecurity. userdetails. UserDetails user = new User (misUser. getName ( ),misUser. getPassword ( ),MisUtils. parseBoolean (misUser. getEnable ( ) ), true,true, true,getAuthoritiesByUsernameQuery (username ) ); return user; } else return null; } /** * 根据用户名查找角色 * @param username * @return GrantedAuthority[] 用户角色 * @throws DataAccessException */ public GrantedAuthority [ ] getAuthoritiesByUsernameQuery ( String username ) throws DataAccessException { sample. mappings. user. User misUser = (sample. mappings. user. User )baseDao. loadByKey (sample. mappings. user. User. class,"name",username ); if (misUser != null ) { GrantedAuthority [ ] grantedAuthoritys = cache. getAuthorityFromCache (misUser. getName ( ) ); if (grantedAuthoritys == null ) { Set roles = misUser. getRoles ( ); Iterator it = roles. iterator ( ); List list = new ArrayList ( ); while (it. hasNext ( ) ) { GrantedAuthorityImpl gai = new GrantedAuthorityImpl ( ( (Role )it. next ( ) ). getName ( ) ); list. add (gai ); } grantedAuthoritys = (GrantedAuthority [ ] ) list. toArray ( new GrantedAuthority [ 0 ] ); cache. putAuthorityInCache (misUser. getName ( ),grantedAuthoritys ); return grantedAuthoritys; } return grantedAuthoritys; } return null; } public IBaseDao getBaseDao ( ) { return baseDao; } public void setBaseDao (IBaseDao baseDao ) { this. baseDao = baseDao; } public AuthorityBasedUserCache getCache ( ) { return cache; } public void setCache (AuthorityBasedUserCache cache ) { this. cache = cache; } } 通过以上对acegi 的 处理,足以满足我们目前在spring下基于RBAC的动态权限管理。同时在对频繁的数据库查询上使用了Ehcache作为缓存,在性能上有了很大的改善。 |