??在業(yè)務(wù)邏輯中私蕾,不同的角色擁有各自的職責(zé)穆役,由于職責(zé)不同,所負(fù)責(zé)的功能也不一樣赢乓,就擁有了不同的權(quán)限等級(jí)忧侧。
??而權(quán)限驗(yàn)證通常以攔截請(qǐng)求來實(shí)現(xiàn),但不可能在每個(gè)Controller方法中都編寫一段權(quán)限驗(yàn)證的代碼牌芋,于是使用自定義注解就成了很好的解決方式。
示例
??假設(shè)有一個(gè)業(yè)務(wù)場(chǎng)景松逊,需要判斷用戶所屬的角色是否和要求角色匹配躺屁,那么可能需要進(jìn)行如下操作:
@RequestMapping(value = "/addItem",method = RequestMethod.POST)
public Response addItemByAdmin(HttpServletRequest request,@RequestBody Map<String,Object> jsonObj){
// 獲取用戶令牌
String token = request.getHeader("Token");
// 獲取用戶信息
User user = userService.findUser(token);
// 判斷角色是否為管理員
if(user.getRole()!=Role.ADMIN){
// 若角色不匹配
return Response.fail("只有管理員可以進(jìn)行此操作");
}
// 如果角色匹配,進(jìn)入業(yè)務(wù)流程
.....
}
乍一看好像沒有問題经宏,但如果有很多業(yè)務(wù)場(chǎng)景都需要進(jìn)行角色驗(yàn)證犀暑,那這段代碼豈不是每個(gè)方法都要復(fù)制一遍?當(dāng)然不行烁兰。
新建注解[1]
??示例demo提出的需求很簡(jiǎn)單耐亏,只需要一個(gè)角色信息即可完成業(yè)務(wù),所以注解可以這樣設(shè)計(jì):
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface PermissionLimit {
// 注解需要設(shè)置的角色等級(jí)
int role();
// 管理員
int ROLE_ADMIN = 103;
// 會(huì)員
int ROLE_VIP = 102;
// 標(biāo)準(zhǔn)
int ROLE_STANDARD = 101;
// 被封禁
int ROLE_LOCK = 100;
}
- 此處Target設(shè)置為METHOD沪斟,是因?yàn)橐话悴煌?qǐng)求會(huì)設(shè)置不同權(quán)限广辰,如果需要按角色編寫Controller,也可以將Target改為TYPE
在攔截器中配置驗(yàn)證
??需要先在攔截器中獲取注解主之,使用注解中設(shè)置的角色對(duì)當(dāng)前用戶進(jìn)行驗(yàn)證择吊,若驗(yàn)證成功才能進(jìn)入方法中執(zhí)行業(yè)務(wù)流程。在攔截器的preHandle中進(jìn)行如下操作:
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws BusinessException {
// 原攔截器操作
.....
// 角色驗(yàn)證
if(!permissionLimit(request, handler)){
return false;
}
// 其他
.....
return true;
}
private boolean permissionLimit(HttpServletRequest request, Object handler) throws BusinessException {
// 如果不是方法
if (!(handler instanceof HandlerMethod)){
return true;
}
// 獲取注解
PermissionLimit pl = ((HandlerMethod)handler).getMethodAnnotation(PermissionLimit.class);
// 如果沒有注解就跳過
if(pl == null){
return true;
}
// 獲取用戶令牌
String token = request.getHeader("Token");
// 獲取用戶信息
User user = userService.findUser(token);
// 判斷角色和注解的設(shè)置是否匹配
return user.getRole()==pl.role()
}
- 此處拋出異常而不是直接返回響應(yīng)信息是因?yàn)楫惓槽奕?杀籈xceptionHandler捕獲几睛,由它進(jìn)行統(tǒng)一處理
使用方式
??示例中的方法此時(shí)可改為:
@PermissionLimit(role = PermissionLimit.ADMIN)
@RequestMapping(value = "/addItem",method = RequestMethod.POST)
public Response addItemByAdmin(@RequestBody Map<String,Object> jsonObj){
// 進(jìn)入業(yè)務(wù)流程
.....
}
如有錯(cuò)誤,歡迎指出粤攒,謝謝