RBAC是各類系統(tǒng)中應(yīng)用最廣泛的訪問(wèn)控制機(jī)制。使用RBAC時(shí)姨伤,一個(gè)比較復(fù)雜的問(wèn)題是維護(hù)數(shù)據(jù)庫(kù)中的規(guī)則列表。本文使用Java注解實(shí)現(xiàn)了規(guī)則的自動(dòng)提取庸疾,程序員只需要在需要權(quán)限控制的方法上方用RBAC注解說(shuō)明規(guī)則名乍楚,規(guī)則url和能使用該方法的角色名即可。
RBAC表結(jié)構(gòu)
一届慈、RBAC注解
package?annotation.rbac;??
import?java.lang.annotation.ElementType;??
import?java.lang.annotation.Retention;??
import?java.lang.annotation.RetentionPolicy;??
import?java.lang.annotation.Target;??
@Retention(RetentionPolicy.RUNTIME)??
@Target(value?=?{ElementType.METHOD})??
public?@interface?Rbac?{??
????String?url();??
????String[]?role();??
????String?name();??
}??
二徒溪、角色定義
package?annotation.rbac;??
public?class?Roles?{??
public?static?final?String?ADMIN="admin";??
public?static?final?String?MANAGER="manager";??
public?static?final?String?TEACHER="teacher";??
public?static?final?String?STUDENT="student";??
}??
三、在控制器上使用注解
package?annotation.rbac;??
public?class?UserController?{??
@Rbac(name="添加用戶",url="/admin/adduser",role={Roles.ADMIN,Roles.MANAGER})??
public?String?addUser(String?username,String?password){??
return?"success";??
????}??
@Rbac(name="用戶注銷",url="/logout",role={Roles.ADMIN,Roles.MANAGER,Roles.STUDENT,Roles.TEACHER})??
public?String?logout()??
????{??
return?"success";??
????}??
@Rbac(name="成績(jī)查詢",url="/query",role=Roles.STUDENT)??
public?String?query(){??
return?"success";??
????}??
@Rbac(name="成績(jī)錄入",url="/insert",role=Roles.TEACHER)??
public?String?insert(){??
return?"success";??
????}??
}??
四金顿、注解解析器臊泌,用于提取RBAC規(guī)則。進(jìn)行修改之后可對(duì)所有控制器進(jìn)行分析并生成數(shù)據(jù)插入數(shù)據(jù)庫(kù)揍拆。
package?annotation.rbac;??
import?java.lang.annotation.Annotation;??
import?java.lang.reflect.Method;??
import?java.util.HashMap;??
import?java.util.Set;??
public?class?RbacParser?{??
public?static?void?main(String[]?args)?{??
try?{??
HashMap?roleTable=new?HashMap<>();??
int?ruleId=1;??
Class?c?=?Class.forName("annotation.rbac.UserController");??
????????????Method[]?methods=c.getMethods();??
for(Method?m:methods){??
????????????????Annotation[]?annotations=m.getDeclaredAnnotations();??
for(Annotation?annotation:annotations){??
if(annotation?instanceof?Rbac){??
????????????????????????Rbac?rbacAnnotation=(Rbac)?annotation;??
????????????????????????String?url=rbacAnnotation.url();??
????????????????????????String?name=rbacAnnotation.name();??
????????????????????????String[]?methodRoles=rbacAnnotation.role();??
//后面需要將這條語(yǔ)句轉(zhuǎn)換為SQL插入到數(shù)據(jù)庫(kù)表rules??
System.out.printf("rule_id:%d?name:%s?url:%s\n",ruleId,name,url);??
//將角色具有權(quán)限的rule的編號(hào)拼接成逗號(hào)分隔的字符串渠概,存放到HashMap??
for(String?role:methodRoles){??
if(roleTable.containsKey(role)){??
????????????????????????????????String?s=roleTable.get(role);??
roleTable.put(role,?s+","+ruleId);??
}else{??
????????????????????????????????roleTable.put(role,?String.valueOf(ruleId));??
????????????????????????????}??
????????????????????????}??
????????????????????????ruleId++;??
????????????????????}??
????????????????}??
????????????}??
//后面需要將下面的輸出語(yǔ)句轉(zhuǎn)換為SQL插入到數(shù)據(jù)庫(kù)表Roles??
????????????Set?roleNames?=?roleTable.keySet();??
for(String?roleName:roleNames){??
System.out.printf("role_name:%s?rules:%s\n",roleName,roleTable.get(roleName));??
????????????}??
}catch?(Exception?e)?{??
throw?new?RuntimeException(e);??
????????}??
????}??
}??