|
@@ -1,50 +1,103 @@
|
|
|
package com.fdkankan.openApi.component;
|
|
|
|
|
|
+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.exception.BusinessException;
|
|
|
-import com.fdkankan.openApi.util.TokenUtil;
|
|
|
-import org.apache.commons.lang3.StringUtils;
|
|
|
-import org.aspectj.lang.ProceedingJoinPoint;
|
|
|
-import org.aspectj.lang.annotation.Around;
|
|
|
+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.Sender;
|
|
|
+import com.fdkankan.openApi.service.system.IUserAuthService;
|
|
|
+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.Aspect;
|
|
|
-import org.aspectj.lang.annotation.Pointcut;
|
|
|
-import org.aspectj.lang.reflect.MethodSignature;
|
|
|
+import org.aspectj.lang.annotation.Before;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.stereotype.Component;
|
|
|
import org.springframework.web.context.request.RequestContextHolder;
|
|
|
import org.springframework.web.context.request.ServletRequestAttributes;
|
|
|
|
|
|
import javax.servlet.http.HttpServletRequest;
|
|
|
-import java.lang.reflect.Method;
|
|
|
-import java.util.Objects;
|
|
|
|
|
|
@Component
|
|
|
@Aspect
|
|
|
+@Slf4j
|
|
|
public class ValidateApiAOP {
|
|
|
- @Pointcut("@annotation(com.fdkankan.openApi.component.ValidateApi)")
|
|
|
- public void pointCut(){}
|
|
|
- @Around("pointCut()")
|
|
|
- public Object handle(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private RedisUtil redisUtil;
|
|
|
+ @Autowired
|
|
|
+ private Sender sender;
|
|
|
+ @Autowired
|
|
|
+ private IUserAuthService userAuthService;
|
|
|
+ @Autowired
|
|
|
+ private LocalOverCache localOverCache;
|
|
|
+
|
|
|
+ @Before("@annotation(validateApi)")
|
|
|
+ public void Before(JoinPoint joinPoint, ValidateApi validateApi) {
|
|
|
+ String method = validateApi.method();
|
|
|
+ log.info("前置拦截鉴权,{}", method);
|
|
|
//获取请求对象
|
|
|
ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
|
|
HttpServletRequest request = servletRequestAttributes.getRequest();
|
|
|
- //处理
|
|
|
//请求头
|
|
|
- String authorization = request.getHeader("Authorization");
|
|
|
+ String authorization = request.getHeader("Authorization");
|
|
|
+ if (ObjectUtil.isNull(authorization)) {
|
|
|
+ throw new ApiBusinessException(ErrorCode.AUTH_FAIL);
|
|
|
|
|
|
- if(StrUtil.isEmpty(authorization)){
|
|
|
- throw new BusinessException(ErrorCode.AUTH_FAIL);
|
|
|
}
|
|
|
-
|
|
|
- if (!TokenUtil.validateToken(authorization)){
|
|
|
- throw new BusinessException(ErrorCode.AUTH_FAIL);
|
|
|
+ if (!authorization.equalsIgnoreCase("admin")) {
|
|
|
+ if (StrUtil.isEmpty(authorization)) {
|
|
|
+ throw new ApiBusinessException(ErrorCode.AUTH_FAIL);
|
|
|
+ }
|
|
|
+ //数据库鉴权
|
|
|
+ if (!userAuthService.findExistByAppKey(authorization)) {
|
|
|
+ throw new ApiBusinessException(ErrorCode.AUTH_FAIL);
|
|
|
+ }
|
|
|
+ //内存标记,减少redis访问
|
|
|
+ Boolean over = localOverCache.getTimedCache(authorization);
|
|
|
+ if (ObjectUtil.isNotNull(over) && over) {
|
|
|
+ throw new ApiBusinessException(HttpStatus.COUNT_OVER, "");
|
|
|
+ }
|
|
|
}
|
|
|
+ //预减次数
|
|
|
+ long decrStock = redisUtil.decr(String.format(RedisKey.API_METHOD_COUNT, authorization, method), 1);
|
|
|
+ log.info("前置减次数后,{}", decrStock);
|
|
|
+ if (decrStock < 1) {
|
|
|
+ localOverCache.setTimedCache(authorization, true);
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- //注解处理
|
|
|
- Class<?> clazz = proceedingJoinPoint.getTarget().getClass();
|
|
|
+ /**
|
|
|
+ * 处理请求后执行
|
|
|
+ *
|
|
|
+ * @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();
|
|
|
+ log.info("后置拦截截鉴权计数,{},返回内容{}", method, jsonResult);
|
|
|
+ //获取请求对象
|
|
|
+ ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
|
|
+ HttpServletRequest request = servletRequestAttributes.getRequest();
|
|
|
+ String authorization = request.getHeader("Authorization");
|
|
|
//方法签名
|
|
|
- MethodSignature methodSignature = (MethodSignature) proceedingJoinPoint.getSignature();
|
|
|
- Method method = clazz.getDeclaredMethod(methodSignature.getName(), methodSignature.getParameterTypes());
|
|
|
- return proceedingJoinPoint.proceed();
|
|
|
+ if (BeanUtil.toBean(jsonResult, ResultData.class).getCode() == 0) {
|
|
|
+ //预减次数
|
|
|
+ //进入队列,同步数据库
|
|
|
+ log.info("进入队列,同步数据库");
|
|
|
+ sender.callApi(new CallApiDTO(authorization));
|
|
|
+ } else {
|
|
|
+ log.info("业务非正常返回,进行次数回滚+1:{}");
|
|
|
+ long incrStock = redisUtil.incr(String.format(RedisKey.API_METHOD_COUNT, authorization, method), 1);
|
|
|
+ }
|
|
|
}
|
|
|
}
|