继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

使用AOP实现权限拦截校验

0xcaffebabe
关注TA
已关注
手记 43
粉丝 10
获赞 21

aop的好处就在于它可以只让你写一次代码,然后这些代码就可以用于容器当中的所有对象,权限拦截校验是一个表现形式。

那么,我们要如何实现这个功能?

首先,定义一个注解:

/*
* 被该注释修饰的方法都会经过切面拦截校验权限
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Permission {
   PermissionEnum value();
   String msg() default "";
}

这里有一个PermissionEnum枚举类,当然可以直接使用String 代替,不过不推荐,其源码如下:

public enum PermissionEnum {

   LOGIN("login"), // 登录权限
   CREATE_ADMIN("createAdmin"), // 创建其他管理员的权限
   DASHBOARD_VIEW("dashboardView"), // 查看仪表盘数据的权限
   USER_DATA_VIEW("userDataView"), // 查看用户数据的权限
   ;
   private String permission;

   PermissionEnum(String permission) {
       this.permission = permission;

   }

   public String getPermission() {
       return permission;
   }
}

这里,我们控制的权限颗粒度是方法,所以必须使用一个标识符来标志出每个方法,我们只要将Permission注解加到方法之上,就能被切面所拦截,并进行权限校验:

@Permission(PermissionEnum.USER_DATA_VIEW)
   public List<User> findAll(Integer page,Integer length){
       Pageable pageable = PageRequest.of(page,length);
       Page<User> userPage = userRepository.findAll(pageable);
       return userPage.stream().collect(Collectors.toList());

   }

上面是一个方法示例:

接下来就是重点了,切入点的编写:

@Before("pointCut()")
   public void before(JoinPoint joinPoint){
       Signature signature = joinPoint.getSignature();
       MethodSignature methodSignature = (MethodSignature) signature;
       Method method = methodSignature.getMethod();
       var a = method.getAnnotation(Permission.class);

       String msg = null;
       if ("".equals(a.msg())){
           msg = "没有"+a.value().getPermission()+"权限";
       }else{
           msg = a.msg();
       }
       var permission = adminPermissionService.getCurrentAdminPermission();

       try {
           String methodName = a.value().getPermission();
           methodName = methodName.substring(0,1).toUpperCase()+methodName.substring(1,methodName.length());
           Method method1 = permission.getClass().getMethod("get"+methodName);
           Boolean ret = (Boolean) method1.invoke(permission);
           if (ret == null){
               ErrorUtils.error(msg);
           }

           if (!ret){
               ErrorUtils.error(msg);
           }
       } catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
           throw new RuntimeException(e.getMessage());
       }

   }

代码虽然有点长,但做的事并不多,无非就是获取当前登录管理员的权限,然后判断该其切点的权限要求当前管理是否满足,满足就继续运行,否则抛出一个权限错误的异常。

当然,这个权限拦截校验方案是写死的,也就是说你无法根据实际的情况需要添加或者删除的相应权限,因为这是由系统的权限控制方案所限定的,我们权限拦截的目标是方法,不像其他诸如URL的拦截方案,想要修改方法,即拦截目标,就必须修改源码,所以也就没有必要做成高度可自定义化的权限方案。


打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP