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


一、場景

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

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

    

二、為什么使用注解+AOP

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

這兩種方法的區別在於,第一種:比如當前用戶在新聞列表中刪除某篇新聞,但是該用戶並沒有這種權限,此時會拋出異常,我們需要處理異常即可,但是頁面進行跳轉,我們希望用戶在新聞列進行刪除操作的時候,如果沒有該權限則會彈窗提示,而不是跳轉到統一的異常頁面。 第二種,可以實現第一種的不足,但是沒有第一種方便快捷。

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

 

三、實現

    實現的效果:需要校驗權限的方法比如刪除方法del(),只要在該方法上添加自定義注解,即可實現上述效果。

    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.java

/**
 * 類名 :用戶的工具類
 * 用法 :
 * 創建人 : 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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM