java使用AOP进行权限控制等操作

AOP通知类型

  • @Before(前置通知):在连接点执行前执行该通知。
  • @After(后置通知):又名最终通知,在连接点执行完成后(不管成功、失败、异常)都会执行该通知。
  • @AfterReturning(返回通知):在连接点执行完成后执行,若目标方法执行异常则不会执行该通知。
  • @AfterThrowing(异常通知):在连接点执行抛出异常时执行该通知。
  • @Around(环绕通知):结合了上面四种通知,加强版的通知,围绕在连接点前后。

自定义权限控制注解

前置通知方式:

@Target({ElementType.METHOD})
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Order(Ordered.HIGHEST_PRECEDENCE)
public @interface CheckOperation {

    String operationCode();
}
@Aspect
@Component
public class CheckOperationAop {
    
    @Autowired
    HttpServletRequest request;

    @Pointcut(value = "@annotation(XXX.XXX.CheckOperation)")
    public void logAnnotation() {
        
    }

	// 前置通知,方法执行前判断用户是否有权限
    @Before("logAnnotation()")
    public void before(JoinPoint point) {
        MethodSignature methodSignature = (MethodSignature) point.getSignature();
        CheckOperation annotation = methodSignature.getMethod().getAnnotation(CheckOperation.class);
        if (getRequestAttributes() == null) {
            throw new XXXException("获取请求体失败");
        }

        LoginInfo loginInfo = OauthUtils.getCurrentUser();
        String userId;
        if (loginInfo != null) {
            userId = loginInfo.getUserId();
        } else {
            String token = request.getParameter("token").replace("bearer ", "");
            userId = JWT.decode(token).getClaim("userId").asInt().toString();
        }

		// 获取注解参数
        String code = annotation.operationCode();
        if (...) {
            throw new XXXException("用户没有该操作权限");
        }
    }
}
@CheckOperation(operationCode = "0cd7647c-696c-9254-b886-5e3405b1aed2")
@PostMapping("/XXX")
public Object XXX(@Valid @RequestBody XXX xxx) {
}

环绕通知方式:

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

    String operationName();
}
@Aspect
@Component
public class SysOperationLogRecordAop {

    @Autowired
    SysOperationlogMapper sysOperationlogMapper;

    @Autowired
    HttpServletRequest request;

    @Pointcut(value = "@annotation(com.dsh.annotation.SysOperationLogRecord)")
    public void sysOperationLogAnnotation() {
    }

	// 环绕通知,可在方法执行前后做出各种操作
    @Around("sysOperationLogAnnotation()")
    public Object before(ProceedingJoinPoint point) throws Throwable {
        MethodSignature methodSignature = (MethodSignature) point.getSignature();
        SysOperationLogRecord annotation = methodSignature.getMethod().getAnnotation(SysOperationLogRecord.class);

        String userId = OauthUtils.getCurrentUser().getUserId();
        String ip = RequestHeaderUtil.getRemoteHost(request);
        String userAgent = request.getHeader("user-agent");
        String browser = RequestHeaderUtil.getBrowser(userAgent);
        String os = RequestHeaderUtil.getOS(userAgent);
        // 获取注解参数
        String operationDesc = annotation.operationName();
        int operationResult = 1;
        String url = request.getRequestURL().toString();
        // 获取执行方法参数
        Object[] paramValues = point.getArgs();

        // 锁车指令有三种,判断一下是哪种指令
        if(operationDesc.equals("下发锁车指令")){
            RequestOrder requestOrder = (RequestOrder) paramValues[0];
            switch (requestOrder.getLockModel()){
                case 0:
                    operationDesc = "下发查询指令";
                    break;
                case 1:
                    operationDesc = "下发解锁指令";
                    break;
                default:
            }
        }

        BaseApiResult proceed = null;
        JSONObject proceed2 = null;

        try {
        	// 执行方法,获取执行结果
            Object methodResult = point.proceed();
            if(methodResult instanceof BaseApiResult){
                proceed = (BaseApiResult) methodResult;
                if(proceed.getCode() != 1){
                    operationResult = -1;
                }
            }else if(methodResult instanceof JSONObject){
                proceed2 = (JSONObject) methodResult;
                if(!(boolean)proceed2.get("success")){
                    operationResult = -1;
                }
            }

        } catch (Throwable e) {
            operationResult = -1;

            // 每次操作记录日志
            sysOperationlogMapper.insert(SysOperationlog.builder().userId(Integer.valueOf(userId))
                    .operationTime(System.currentTimeMillis()).operationDesc(operationDesc)
                    .operationResult(operationResult).ip(ip).browser(browser).os(os).url(url)
                    .parameter(Arrays.toString(paramValues)).build());

            throw e;
        }

        // 每次操作记录日志
        sysOperationlogMapper.insert(SysOperationlog.builder().userId(Integer.valueOf(userId))
                .operationTime(System.currentTimeMillis()).operationDesc(operationDesc)
                .operationResult(operationResult).ip(ip).browser(browser).os(os).url(url)
                .parameter(Arrays.toString(paramValues)).build());

        return proceed == null ? proceed2 : proceed;
    }
}
@SysOperationLogRecord(operationName = "下发锁车指令")
@PostMapping("/XXX")
public BaseApiResult<?> XXX(@Valid @RequestBody XXX xxx) {
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值