• springboot接口访问权限AOP实现


    场景

    现在有个系统,很多接口只需要登录就可以访问,但是有些接口需要授予并验证权限。如果用注解controller的方式控制接口的权限呢?

    1、注解声明代码

    这个注解是要装饰在controller接口上的。

    按照一般权限的设计,有用户(user)-角色(role)-权限(permission)三种实体,他们之间都是多对多关系。

    注解声明的时候,可以配置要验证的角色(role)或权限(menu)。所以我这里有两个变量。

    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    /**
     * @Author: ivan
     * @Description:
     * @Date: Created in 19:58 18/5/28
     * @Modified By:
     */
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Authentication {
        long[] role() default {};
        long[] menu() default {};
    
    }

    2、Authentication权限验证Advice

    我们以验证角色为例。

    第一步,先从controller参数的request cookie里拿到用户登录信息,获取userId,我这里是card。

    第二步,查询用户角色数据库,获取该user拥有哪些权限。

    第三部,跟@Authentication里配置的权限进行比较,校验成功返回数据,校验失败返回错误码。

    使用localthread记录了权限验证处理时间,用来进行监控。

    /**
     * @Author: ivan
     * @Description:
     * @Date: Created in 20:00 18/5/28
     * @Modified By:
     */
    @Aspect
    @Component
    @Order(-10)
    public class AuthenticationAspect {
    
        private static Logger logger = LoggerFactory.getLogger(AuthenticationAspect.class);
    
        @Autowired
        private AuthDao authDao;
    
        ThreadLocal<Long> beginTime = new ThreadLocal<Long>();
    
        @Pointcut("@annotation(authentication)")
        public void AuthenticationService(Authentication authentication) {
        }
    
        @Around("AuthenticationService(authentication)")
        public Object doAround(ProceedingJoinPoint joinPoint, Authentication authentication) throws Throwable{
            beginTime.set(System.currentTimeMillis());
            String card = null;
            List<Long> roleList = new ArrayList<>();
            for (Object arg : joinPoint.getArgs()) {
                if (arg != null && arg.getClass() == RequestFacade.class) {
                    RequestFacade request = (RequestFacade) arg;
                    card = CookieUtils.getCardFromCookie(request);
                    if (StringUtils.isEmpty(card)) {
                        return JsonResult.buildFailResult(-1, 1000, "权限验证未通过", null);
                    }
                    List<Role> roles = authDao.getRolesByCard(card);
                    for (Role role : roles) {
                        roleList.add(role.getId());
                    }
                    break;
                }
            }
            logger.info("[authentication] user={}, roles={}", card, roleList);
            long[] aims = authentication.role();
            boolean isPass = false;
            for (long aim : aims) {
                if (roleList.contains(aim)) {
                    isPass = true;
                }
            }
            if (isPass) {
                logger.info("[authentication] authentication pass, cost time: {}", System.currentTimeMillis() - beginTime.get());
                return joinPoint.proceed();
            } else {
                beginTime.set(System.currentTimeMillis());
                logger.info("[authentication] authentication reject, cost time: {}", System.currentTimeMillis() - beginTime.get());
                return JsonResult.buildFailResult(-1, 1000, "权限验证未通过", null);
            }
    
        }
    
    
    }

    3、使用方法

    1、Authentication直接装饰在controller接口上,参数是role={2},即用户拥有2这个角色的时候拥有访问这个接口的权限。

    2、controller第一个参数要是HttpServletRequest request,不然上面从request里面拿用户信息会失败。(这个地方确实不方便)

    /**
     * 审核接口
     *
     * @author ivan
     * @date 2018/08/02
     */
    @Controller
    @RequestMapping("/audit")
    public class AuditController {
        private static final Logger LOGGER = LoggerFactory.getLogger(AuditController.class);
        @Resource
        private AuditService auditService;

    @ResponseBody @PostMapping(value = "/review") @Authentication(role = {2}) public JsonResult review(HttpServletRequest request, @RequestBody AduitDTO aduitDTO) { LOGGER.info("[aduitDTO] video service aduitDTO={}" + aduitDTO); UserInfo userInfo = CookieUtils.getLoginInfoFromCookie(request); aduitDTO.setCard(userInfo.getCard()); int status = 0; aduitDTO.setAuditor(userInfo.getCard()); JsonResult jsonResult = null; if (ListEnum.ZERO.toString().equals(aduitDTO.getType())) { if (null != aduitDTO.getStatus() && ListEnum.ONE.toString().equals(aduitDTO.getStatus())) { status = auditService.review(aduitDTO); jsonResult = JsonResult.buildSuccessResult("审核通过"); } if (null != aduitDTO.getStatus() && ListEnum.TWO.toString().equals(aduitDTO.getStatus())) { if(StringUtils.isEmpty(aduitDTO.getReason())){ return JsonResult.buildFailResult(1, 102, "请添加不通过原因!", null); } aduitDTO.setAuditTime(DateUtils.parseDateToStr(new Date() ,"yyyy-MM-dd HH:mm:ss")); status = auditService.updateAduit(aduitDTO); jsonResult = JsonResult.buildSuccessResult("审核不通过"); } } return jsonResult; } }
  • 相关阅读:
    JS基础的入口函数以及函数
    JS基础的数组
    JS基础的数学函数、日期时间函数、运算符和流程语句
    JS基础的引入、注释、变量、数据类型和输出语法
    CSS3的动画、弹性盒子和多媒体查询
    CSS3的颜色(RGBA)透明度、渐变颜色、图片、旋转和过渡
    CSS3边框、背景和字体
    java基础(九)---继续聊聊map
    java基础(八)---map
    java基础(七)--- set
  • 原文地址:https://www.cnblogs.com/kangoroo/p/10616402.html
Copyright © 2020-2023  润新知