权限验证原理篇

2015-08-20学到的权限验证

“权限管理”是“权限验证”的基础
1)权限管理
登录时算出用户的所有权限:
①通过用户的角色找出相应权限
用户–>角色–>权限

由用户名得到userId,从user_role关联表中获得roleId,再从role_auth关联表中获得authId,由authId获得AuthorityInfo,然后获得AuthName,List<AuthorityInfo> authsByRole = getAuthByRole(currentId);
(这里只是参考,有待优化)

②通过直接赋予该user权限
List authsByUser = getAuthByUser(currentId);

将上面的结果都放到AuthorityInfo中
③把该用户的权限信息整合放到缓存Buffer中

2 )权限验证
在登录时,用户要同时获取用户权限,以下以LoginAction为例子
①找出用户有哪些权限 acl.authorized(auth.getAuthCode())

@SuppressWarnings("serial")
public class LoginAction extends BaseLoginAction {
    private static final Logger logger = LoggerFactory.getLogger(LoginAction.class);
    private static final String prefix = "open";

    @Override
    protected Boolean hasAnyAuthority(ACL acl) {
        Boolean result = false;
        Map<String,Object> queryMap = new HashMap<String,Object>();
        queryMap.put("authCode", prefix);

        **List<AuthorityInfo> openAUthorityInfoList = authorityInfoManager.getAuthorityInfoList(queryMap);**
    //找到open下的所有权限  
        for(AuthorityInfo auth:openAUthorityInfoList) {
            if(**acl.authorized(auth.getAuthCode())**) {
            //判断该用户有哪些权限
                result = true;
                break;
            }
        }

        return result;
    }

getAuthorityInfoList(queryMap)的相应myBatis语句
<select id="getAuthorityInfoList" parameterType="java.util.Map" resultMap="BaseResultMap">
        select
            <include refid="Base_Column_List" />
        from
            t_dsp_auth_authority_info
        <where> 
            <if test="uthCode != null">
                and auth_code like '%${authCode}%'
            </if>
                and auth_level != 0
        </where>
    </select>
    找出了所有以open开头的authCode

②确认用户在某个权限上的力度,比如商品信息管理的增删改查
acl.check(auth.getAuthCode(),auth.getAuthStr());
//第一个参数是权限Code,第二个参数是该权限下的所有权限力度
将所有权限力度与相应用户权限(ACLNode数据结构)的 authValue(比如1001,表示有增和查的操作力度,没有删和改的力度)进行验证,即确定要验证的权限是否在当前用户的权限集合中

ACL.java写出了验证方法(authorized(String authCode)和check(String authCode, String[] idxes),分别验证用户是否有某权限以及某权限操作力度)

public class ACL extends com.cmcc.cxb.common.Constants {
    //nodes的key是authCode,代表某个权限
        private Map<String, ACLNode> nodes;//用户在该权限下的权限信息Map,最主要体现在authValue,表示该用户对应该权限的权限力度
        private Integer userType;

        public ACL(Map<String, ACLNode> nodes, Integer userType) {
            super();
            this.userType = userType;
            this.nodes = nodes;
        }

        public boolean authorized(String authCode) {
            return authorized(authCode,true);
        }

        public boolean authorized(String authCode, boolean checkType) {
            return ( checkType && AUTH_USER_TYPE_SUPER.equals(userType) ) || nodes.get(authCode) != null;
        }

        public boolean check(String authCode, String[] idxes) {

            if(AUTH_USER_TYPE_SUPER.equals(userType))
                return true;

            boolean ret = false;
            if (idxes != null)
                for (int ii = 0; ii < idxes.length; ii++) {
                    ret = ret || check(authCode, idxes[ii]);   //如果idxes数组中有任何一个权限检查通过,那么返回true
                }
            else
                ret = authorized(authCode);
            return ret;
        }

        //权限检查!!!!!!!!!
        public boolean check(String authCode ,String auth){
            return check(authCode, auth, true);
        }

        //authCode:代表一个权限
        //auth:某个权限的额最细粒度的操作,例如删除delete
        public boolean check(String authCode ,String auth, boolean checkType){

            if(checkType && AUTH_USER_TYPE_SUPER.equals(userType))
                return true;

            //ACLNode的  AuthValue是什么??
            ACLNode node = nodes.get(authCode);     //根据authCode获取权限节点
            if (node == null)
                return false;

            String[] authes = node.getAuthes();
            String authValue = node.getAuthValue();

            try {
                int index = ArrayUtils.indexOf(authes, auth);   //确定要验证的权限是否在当前用户的权限集合中
                int te = ArrayUtils.indexOf(authes, "test");
                if(index == -1)
                    return false;
                return check(authValue,index);
            } catch (Exception e) {
                return false;
            }
        }

        public static boolean check(String authValue,int idx) {
            if (authValue != null && authValue.length() > idx)
                return (authValue.charAt(idx) == '1');
            else if(authValue!=null)
                return false;
            return true;
        }

        public Map<String, ACLNode> getNodes() {
            return nodes;
        }

        public void setNodes(Map<String, ACLNode> nodes) {
            this.nodes = nodes;
        }

        public Integer getUserType() {
            return userType;
        }

        public void setUserType(Integer userType) {
            this.userType = userType;
        }

}

ACLNode.java是用户在该权限下的权限信息结构体

public class ACLNode {
    private Integer authId;
    private String[] authes;   //某个叶子权限的最小粒度操作,例如增加、删除、修改、排序等具体操作。
    private String authValue;   //用户在该权限下的权限力度
    private Integer authOption;

    public Integer getAuthId() {
        return authId;
    }

    public String[] getAuthes() {
        return authes;
    }

    public String getAuthValue() {
        return authValue;
    }

    public Integer getAuthOption() {
        return authOption;
    }

    public ACLNode(Integer authId, String[] authes, String authValue,
            Integer authOption) {
        super();
        this.authId = authId;
        this.authes = authes;
        this.authValue = authValue;
        this.authOption = authOption;
    }
    /**
     * 将两个节点合并成一个
     * @param anotherNode
     */
    public void merge(ACLNode anotherNode){
        //为空直接返回
        if(anotherNode==null)
            return;
        //authes 相同的才允许合并
        if(!ArrayUtils.isEquals(authes, anotherNode.getAuthes()))
            return;

//      authOption = Math.max(authOption, anotherNode.getAuthOption());
        if(authValue==null)
            authValue = anotherNode.getAuthValue();
        else{
            String tmp = "";
            for(int i=0;i<authes.length;i++){
                if( ACL.check(authValue,i) || ACL.check(anotherNode.getAuthValue(),i))
                    tmp += "1";
                else
                    tmp += "0";
            }
            authValue = tmp;
        }
    }

}

注:比如authorized()用于点击信息管理后显示的用户的权限,确认有这些权限后,点击某个权限(比如商品信息管理)再去调用check()确认该用户对这个权限的权限力度

3)存于缓存Buffer
便于验证,将每次用户的权限验证结果存于缓存,每次验证先到缓存中查询,再到数据库查询

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值