使用自定義註解和AOP管理shiro權限

1、場景

    在使用shiro框架的時候,遇到了這樣的需求:本系統有多個用戶,每一個用戶分配不一樣角色,每一個角色的權限也不一致。好比A用戶擁有新聞列表的增刪改查權限,而B用戶只有查看新聞列表的權限,而沒有刪除、新增、修改的權限,此時有3種方案:一、不給B用戶分配刪除、新增、修改的菜單,這樣用戶就沒法點擊從而沒法操做。二、給B用戶分配菜單,後臺中進行增刪改查操做時都要進行權限驗證。  三、給B用戶分配菜單而且進行操做的時候校驗權限。java

    顯然,第二、3種方案比第1中方案要安全。本系統中使用第二種方案。安全

    

2、爲何使用註解+AOP

    使用shiro過程當中通常都會自定義Realm,Realm主要進行權限和登陸的校驗,當校驗登陸用戶是否有某個權限的時候,有2種方式:一、使用註解 @RequiresPermissions("news:*")  來判斷用戶是否有news的全部權限。   二、使用Subject.isPermitted("news:*") 方法判斷用戶是否有news的全部權限。  app

這兩種方法的區別在於,第一種:好比當前用戶在新聞列表中刪除某篇新聞,可是該用戶並無這種權限,此時會拋出異常,咱們須要處理異常便可,可是頁面進行跳轉,咱們但願用戶在新聞列進行刪除操做的時候,若是沒有該權限則會彈窗提示,而不是跳轉到統一的異常頁面。 第二種,能夠實現第一種的不足,可是沒有第一種方便快捷。框架

    爲了綜合上述兩種的有點以及缺點,實現shiro校驗權限時有異常但不刷新頁面,同時以註解的形式使用。工具

 

3、實現

    實現的效果:須要校驗權限的方法好比刪除方法del(),只要在該方法上添加自定義註解,便可實現上述效果。ui

    3.1    自定義註解

/**
 * 類名 :權限控制註解
 * 用法 :
 * 建立人 : shyroke
 * 時間:2018/12/18 10:33
 */

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface PermissionAnnotation {

    String permissionName();

}

    

    3.2    編寫切面

/**
 * 類名 :權限的切面類
 * 用法 :
 * 建立人 : 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;
        }

    }
}

 

    3.3    使用

@PermissionAnnotation(permissionName = "boke:*")
@PostMapping(value = "desc")
@ResponseBody
public R desc(){
    return R.ok("刪除成功!");
}

 

    3.4    結果

image.png

相關文章
相關標籤/搜索