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
便于验证,将每次用户的权限验证结果存于缓存,每次验证先到缓存中查询,再到数据库查询