Spring Aop就是我们常说的面向切面编程,它和IOC构成了spring体系的两大核心,玩明白了这两个,spring就算玩会了。。
spring aop可以干很多事,他就类似于拦截器,能在你的目标方法之前或者之后做一些事儿(类似于方法的增强),例如:权限校验、日志记录、统计等

本文主要讲的是如何利用spring aop实现权限校验和控制

一、首先定义接口(有点spring security那意思了)

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

}

二、定义切面

我们的权限控制是根据RBAC模型进行的,也就是说一个用户对应多个角色,已经角色对应多种权限,基于这个模型,以下代码就是大体思路

@Slf4j
@Aspect
@Component
public class AnnotationAopTwo {

    @Autowired
    private HttpServletRequest request;
    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private SysRoleService sysRoleService;


    @Pointcut("@annotation(com.qcby.device.manage.annotation.Authority)")
    public void viewRecordsPoinCut(){}


    @Around("viewRecordsPoinCut()")
    public Object Annotation(ProceedingJoinPoint joinPoint) throws Throwable{
        log.info("---进入aopAround通知---");
        //因为在登录之后会将用户信息存入缓存当中
        //从缓存中获取登录者信息
        SysUser sysUser = redisUtil.get("SysUser");
        
        //获取角色id
        List<Long> roleIds =  sysUser.getRoleIds();

        Set<String> powerStringSet = new HashSet<>();
        for (Long roleId : roleIds) {
            //获取角色所对应的权限字符串
            //权限字符串和访问路径相同,例如查询权限:/rest/user/listPage,删除权限:/rest/user/delete等等...
            //这里可以优化为直接从缓存当中获取,可以节省很多时间个资源
            List<String> powerString = sysRoleService.getPowerString(roleId);
            
            //因为权限字符串可能重复,所以用Set集合保存起来
            powerStringSet.addAll(powerString);
        }
        
        //获取请求的url
        String url = request.getRequestURI();
        log.info("===开始进行权限校验===");
        if(!powerStringSet.contains(url)){
            return ResultJson.error("权限不足");
        }
        
        return joinPoint.proceed();
    }
}

上面代码提供了大体思路,其实使用aop实现权限校验逻辑还是很清晰的

  1. 定义接口@Authority
  2. 定义切面和切点,拦截所有添加了@Authority注解的Controller
  3. 定义权限验证的逻辑
  1. 从缓存中获取用户信息
  2. 获取用户的角色id集合
  3. 根据角色id利用Set集合保存起来
  4. 获取请求的路径url
  5. 判断set集合里面有没有该url,如果有则直接返回,,没有就返回权限不足的信息
文章只提供了大致思路和部分代码,还有很多的优化空间,也可以实现类似spring security的功能,自定义@PreAuthorize和属性hasAuthority等等,里面很多功能还有待挖掘…