package com.fdkankan.openApi.aop; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import com.fdkankan.common.constant.ErrorCode; import com.fdkankan.common.constant.ServerCode; import com.fdkankan.openApi.constant.HttpStatus; import com.fdkankan.openApi.constant.RedisKey; import com.fdkankan.openApi.exception.ApiBusinessException; import com.fdkankan.openApi.mq.dto.CallApiDTO; import com.fdkankan.openApi.mq.sender.CallApiSender; import com.fdkankan.openApi.service.system.IUserAuthInfoService; import com.fdkankan.redis.util.RedisUtil; import com.fdkankan.web.response.ResultData; import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.http.HttpServletRequest; @Order(999) @Component @Aspect @Slf4j public class ValidateApiAOP { @Autowired private RedisUtil redisUtil; @Autowired private CallApiSender callApiSender; @Autowired private IUserAuthInfoService userAuthService; @Autowired private LocalOverCache localOverCache; @Before("@annotation(validateApi)") public void doBefore(JoinPoint joinPoint, ValidateApi validateApi) { String method = validateApi.method(); boolean counting = validateApi.counting(); log.info("前置拦截鉴权,{}", method); //获取请求对象 ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = servletRequestAttributes.getRequest(); //请求头 String authorization = request.getHeader("Authorization"); if (ObjectUtil.isNull(authorization)) { throw new ApiBusinessException(ErrorCode.AUTH_FAIL); } if (!authorization.equalsIgnoreCase("admin")) { if (StrUtil.isEmpty(authorization)) { throw new ApiBusinessException(ErrorCode.AUTH_FAIL); } //数据库鉴权 userAuthService.checkValidAppKey(authorization); } if (counting) { //判断是否是无限制 boolean isInfinite = redisUtil.sExists(RedisKey.API_METHOD_COUNT_INFINITE, authorization); if(!isInfinite){ //预减次数 long decrStock = redisUtil.decr(String.format(RedisKey.API_METHOD_COUNT, authorization), 1); log.info("前置减次数后,{}", decrStock); if (decrStock < 0) { //次数用完后,redis次数会变成负一,这里需要返还一次,变为0,客户增加次数时,从0增加 redisUtil.incr(String.format(RedisKey.API_METHOD_COUNT, authorization), 1); throw new ApiBusinessException(HttpStatus.COUNT_OVER, ""); } } } } /** * 处理请求后执行 * * @param joinPoint * @param validateApi * @param jsonResult * @return */ @AfterReturning(pointcut = "@annotation(validateApi)", returning = "jsonResult") public void doAfterReturning(JoinPoint joinPoint, ValidateApi validateApi, Object jsonResult) throws NoSuchMethodException { String method = validateApi.method(); boolean counting = validateApi.counting(); log.info("后置拦截截鉴权计数,{},返回内容{}", method, jsonResult); //获取请求对象 ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = servletRequestAttributes.getRequest(); String authorization = request.getHeader("Authorization"); //方法签名 if (BeanUtil.toBean(jsonResult, ResultData.class).getCode() == ServerCode.SUCCESS.code()) { if (counting) { log.info("进入队列,同步数据库"); callApiSender.callApi(new CallApiDTO(authorization)); } } else { if (counting) { log.info("业务非正常返回,进行次数回滚+1:{}"); redisUtil.incr(String.format(RedisKey.API_METHOD_COUNT, authorization), 1); } } } /** * 处理请求后执行 * * @param joinPoint * @param validateApi * @param jsonResult * @return */ @AfterThrowing(throwing = "ex",pointcut = "@annotation(validateApi)") public void doAfterThrowing(Throwable ex, ValidateApi validateApi) throws NoSuchMethodException { String method = validateApi.method(); boolean counting = validateApi.counting(); log.info("后置拦截截鉴权计数,{}", method); //获取请求对象 ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = servletRequestAttributes.getRequest(); String authorization = request.getHeader("Authorization"); if(counting){ redisUtil.incr(String.format(RedisKey.API_METHOD_COUNT, authorization), 1); } } }