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 !=
</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 = ; 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 == -)
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=;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
便于驗證,将每次使用者的權限驗證結果存于緩存,每次驗證先到緩存中查詢,再到資料庫查詢