在使用shiro框架的時候,遇到了這樣的需求:本系統有多個用戶,每一個用戶分配不一樣角色,每一個角色的權限也不一致。好比A用戶擁有新聞列表的增刪改查權限,而B用戶只有查看新聞列表的權限,而沒有刪除、新增、修改的權限,此時有3種方案:一、不給B用戶分配刪除、新增、修改的菜單,這樣用戶就沒法點擊從而沒法操做。二、給B用戶分配菜單,後臺中進行增刪改查操做時都要進行權限驗證。 三、給B用戶分配菜單而且進行操做的時候校驗權限。java
顯然,第二、3種方案比第1中方案要安全。本系統中使用第二種方案。安全
使用shiro過程當中通常都會自定義Realm,Realm主要進行權限和登陸的校驗,當校驗登陸用戶是否有某個權限的時候,有2種方式:一、使用註解 @RequiresPermissions("news:*") 來判斷用戶是否有news的全部權限。 二、使用Subject.isPermitted("news:*") 方法判斷用戶是否有news的全部權限。 app
這兩種方法的區別在於,第一種:好比當前用戶在新聞列表中刪除某篇新聞,可是該用戶並無這種權限,此時會拋出異常,咱們須要處理異常便可,可是頁面進行跳轉,咱們但願用戶在新聞列進行刪除操做的時候,若是沒有該權限則會彈窗提示,而不是跳轉到統一的異常頁面。 第二種,能夠實現第一種的不足,可是沒有第一種方便快捷。框架
爲了綜合上述兩種的有點以及缺點,實現shiro校驗權限時有異常但不刷新頁面,同時以註解的形式使用。工具
實現的效果:須要校驗權限的方法好比刪除方法del(),只要在該方法上添加自定義註解,便可實現上述效果。ui
/** * 類名 :權限控制註解 * 用法 : * 建立人 : shyroke * 時間:2018/12/18 10:33 */ @Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface PermissionAnnotation { String permissionName(); }
/** * 類名 :權限的切面類 * 用法 : * 建立人 : shyroke * 時間:2018/12/18 10:38 */ @Aspect @Component public class PermissionAspect { @Pointcut("@annotation(com.shyroke.daydayzhuan.util.PermissionAnnotation)") private void permisson(){ } /** * 給添加PermissionAnnotation註解的方法校驗權限,而沒必要每一個方法內都判斷權限 * @param joinPoint * @param permissionAnnotation * @return * @throws Throwable */ @Around("permisson()&&@annotation(permissionAnnotation)") public Object advice(ProceedingJoinPoint joinPoint, PermissionAnnotation permissionAnnotation) throws Throwable { R r = null; r = (R) joinPoint.proceed(); String permissionName =permissionAnnotation.permissionName(); if(StringUtils.isEmpty(permissionName)){ r.setFlag(false); r.setMessage("權限名稱不能爲空"); return r; } //校驗當前登陸用戶是否有該權限 boolean isPermission = UserUtils.isPermission(permissionName); if(!isPermission){ r.setFlag(false); r.setMessage("沒有此操做權限!"); } return r; } }
UserUtils.javaget
/** * 類名 :用戶的工具類 * 用法 : * 建立人 : shyroke * 時間:2018/12/18 14:39 */ public class UserUtils { /** * 校驗當前登陸用戶是否有該權限 * @param permissionname 權限名稱 * @return */ public static boolean isPermission(String permissionname) { Subject subject = SecurityUtils.getSubject(); if(subject.isPermitted(permissionname)){ return true; }else{ return false; } } }
@PermissionAnnotation(permissionName = "boke:*") @PostMapping(value = "desc") @ResponseBody public R desc(){ return R.ok("刪除成功!"); }