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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值