使用自定义注解和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

相关文章
相关标签/搜索