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

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

                                      

以下是我的标志实现,大致思路是 根据 页面 的传来的 方法名(即 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作为缓存,在性能上有了很大的改善。

posted @ 2008-03-04 17:33  eafy.ye  阅读(806)  评论(0编辑  收藏  举报