diff --git a/ballcat-common/ballcat-common-log/src/main/java/com/hccake/ballcat/common/log/access/annotation/AccessLogIgnore.java b/ballcat-common/ballcat-common-log/src/main/java/com/hccake/ballcat/common/log/access/annotation/AccessLogIgnore.java new file mode 100644 index 0000000000000000000000000000000000000000..ec896ae24bfd4ad629dfdeee77b3145064f10abc --- /dev/null +++ b/ballcat-common/ballcat-common-log/src/main/java/com/hccake/ballcat/common/log/access/annotation/AccessLogIgnore.java @@ -0,0 +1,20 @@ +package com.hccake.ballcat.common.log.access.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author sound + * @version 1.0 + * @date 2021/10/27 + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface AccessLogIgnore { + + boolean req() default false; + + boolean resp() default false; +} diff --git a/ballcat-log/ballcat-log-biz/src/main/java/com/hccake/ballcat/log/handler/CustomAccessLogHandler.java b/ballcat-log/ballcat-log-biz/src/main/java/com/hccake/ballcat/log/handler/CustomAccessLogHandler.java index d80d2a24089815a8c8c5711b19c9020d39d4f05d..6bd5a766488f49e63baa31d19c6178fae8e378aa 100644 --- a/ballcat-log/ballcat-log-biz/src/main/java/com/hccake/ballcat/log/handler/CustomAccessLogHandler.java +++ b/ballcat-log/ballcat-log-biz/src/main/java/com/hccake/ballcat/log/handler/CustomAccessLogHandler.java @@ -1,8 +1,10 @@ package com.hccake.ballcat.log.handler; +import cn.hutool.core.lang.Pair; import cn.hutool.core.util.URLUtil; import com.hccake.ballcat.common.desensitize.DesensitizationHandlerHolder; import com.hccake.ballcat.common.desensitize.enums.RegexDesensitizationTypeEnum; +import com.hccake.ballcat.common.log.access.annotation.AccessLogIgnore; import com.hccake.ballcat.common.log.access.handler.AccessLogHandler; import com.hccake.ballcat.common.log.constant.LogConstant; import com.hccake.ballcat.common.log.util.LogUtils; @@ -13,6 +15,7 @@ import com.hccake.ballcat.log.model.entity.AccessLog; import com.hccake.ballcat.log.thread.AccessLogSaveThread; import lombok.extern.slf4j.Slf4j; import org.slf4j.MDC; +import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.HandlerMapping; import javax.servlet.http.HttpServletRequest; @@ -23,6 +26,8 @@ import java.util.List; import java.util.Map; import java.util.Optional; +import static org.springframework.web.servlet.HandlerMapping.BEST_MATCHING_HANDLER_ATTRIBUTE; + /** * 访问日志 * @@ -82,14 +87,15 @@ public class CustomAccessLogHandler implements AccessLogHandler { // 非文件上传请求,记录body,用户改密时不记录body // TODO 使用注解控制此次请求是否记录body,更方便个性化定制 - if (!LogUtils.isMultipartContent(request) && !"/system/user/pass/{userId}".equals(matchingPattern)) { + Pair logIgnore = getLogIgnoreInfo(request); + if (Boolean.FALSE.equals(logIgnore.getKey()) && !LogUtils.isMultipartContent(request)) { accessLog.setReqBody(LogUtils.getRequestBody(request)); } // 只记录响应头为 application/json 的返回数据 // 后台日志对于分页数据请求,不记录返回值 - if (!uri.endsWith("/page") && response.getContentType() != null - && response.getContentType().contains(APPLICATION_JSON)) { + if (Boolean.FALSE.equals(logIgnore.getValue()) && (!uri.endsWith("/page") && response.getContentType() != null + && response.getContentType().contains(APPLICATION_JSON))) { accessLog.setResult(LogUtils.getResponseBody(request, response)); } @@ -102,6 +108,17 @@ public class CustomAccessLogHandler implements AccessLogHandler { return accessLog; } + private Pair getLogIgnoreInfo(HttpServletRequest request){ + HandlerMethod handlerMethod = (HandlerMethod) request.getAttribute(BEST_MATCHING_HANDLER_ATTRIBUTE); + if(handlerMethod != null){ + AccessLogIgnore accessLogIgnore = handlerMethod.getMethodAnnotation(AccessLogIgnore.class); + if(accessLogIgnore != null){ + return new Pair<>(accessLogIgnore.req(),accessLogIgnore.resp()); + } + } + return new Pair<>(false,false); + } + /** * 获取参数信息 * @param request 请求信息 diff --git a/ballcat-starters/ballcat-spring-boot-starter-datascope/src/main/java/com/hccake/ballcat/common/datascope/interceptor/DataPermissionAnnotationInterceptor.java b/ballcat-starters/ballcat-spring-boot-starter-datascope/src/main/java/com/hccake/ballcat/common/datascope/interceptor/DataPermissionAnnotationInterceptor.java index e05e573f9f3a9ae7d031b935ba8c59afcfb1c6fc..41b49e74d414239665665ad6dfd498faeee2fd2d 100644 --- a/ballcat-starters/ballcat-spring-boot-starter-datascope/src/main/java/com/hccake/ballcat/common/datascope/interceptor/DataPermissionAnnotationInterceptor.java +++ b/ballcat-starters/ballcat-spring-boot-starter-datascope/src/main/java/com/hccake/ballcat/common/datascope/interceptor/DataPermissionAnnotationInterceptor.java @@ -20,9 +20,8 @@ public class DataPermissionAnnotationInterceptor implements MethodInterceptor { Method method = methodInvocation.getMethod(); // 获取执行类 Object invocationThis = methodInvocation.getThis(); - Class clazz = invocationThis != null ? invocationThis.getClass() : method.getDeclaringClass(); // 寻找对应的 DataPermission 注解属性 - DataPermission dataPermission = DataPermissionFinder.findDataPermission(method, clazz); + DataPermission dataPermission = DataPermissionFinder.findDataPermission(method, invocationThis); DataPermissionAnnotationHolder.push(dataPermission); try { return methodInvocation.proceed(); diff --git a/ballcat-starters/ballcat-spring-boot-starter-datascope/src/main/java/com/hccake/ballcat/common/datascope/interceptor/DataPermissionFinder.java b/ballcat-starters/ballcat-spring-boot-starter-datascope/src/main/java/com/hccake/ballcat/common/datascope/interceptor/DataPermissionFinder.java index 6cc8f7715e440feb7b3dacd29a56c4a19dc7f0fb..ad1d189f90c3e7488e87d8f7da8e71d8f0a08bd3 100644 --- a/ballcat-starters/ballcat-spring-boot-starter-datascope/src/main/java/com/hccake/ballcat/common/datascope/interceptor/DataPermissionFinder.java +++ b/ballcat-starters/ballcat-spring-boot-starter-datascope/src/main/java/com/hccake/ballcat/common/datascope/interceptor/DataPermissionFinder.java @@ -1,8 +1,10 @@ package com.hccake.ballcat.common.datascope.interceptor; import com.hccake.ballcat.common.datascope.annotation.DataPermission; +import org.springframework.core.BridgeMethodResolver; import org.springframework.core.MethodClassKey; import org.springframework.core.annotation.AnnotatedElementUtils; +import org.springframework.util.ClassUtils; import java.lang.reflect.Method; import java.util.Map; @@ -41,11 +43,12 @@ public final class DataPermissionFinder { /** * 从缓存中获取数据权限注解 优先获取方法上的注解,再获取类上的注解 * @param method 当前方法 - * @param clazz 当前类 + * @param targetObject 目标对象 * @return 当前方法有效的数据权限注解 */ - public static DataPermission findDataPermission(Method method, Class clazz) { - Object methodKey = getCacheKey(method, clazz); + public static DataPermission findDataPermission(Method method, Object targetObject) { + Class targetClass = targetObject != null ? targetObject.getClass() : method.getDeclaringClass(); + Object methodKey = getCacheKey(method, targetClass); if (DATA_PERMISSION_CACHE.containsKey(methodKey)) { DataPermission dataPermission = DATA_PERMISSION_CACHE.get(methodKey); @@ -53,10 +56,24 @@ public final class DataPermissionFinder { return EMPTY_DATA_PERMISSION == dataPermission ? null : dataPermission; } + /** + * fix + * 查找注解的顺序,当启用jdk动态代理或桥接方法时候查找顺序 + * spring.aop.proxy-target-class = false + * 1. 当前方法(jdk动态代理、cglib) + * 2. 桥接方法 + * 3. 当前类开始一直找到Object + * */ + Class userClass = ClassUtils.getUserClass(targetClass); + // JDK代理时, 获取实现类的方法声明. method: 接口的方法, specificMethod: 实现类方法 + Method specificMethod = ClassUtils.getMostSpecificMethod(method, userClass); + + specificMethod = BridgeMethodResolver.findBridgedMethod(specificMethod); + // 先查方法,如果方法上没有,则使用类上 - DataPermission dataPermission = AnnotatedElementUtils.findMergedAnnotation(method, DataPermission.class); + DataPermission dataPermission = AnnotatedElementUtils.findMergedAnnotation(specificMethod, DataPermission.class); if (dataPermission == null) { - dataPermission = AnnotatedElementUtils.findMergedAnnotation(clazz, DataPermission.class); + dataPermission = AnnotatedElementUtils.findMergedAnnotation(userClass, DataPermission.class); } DATA_PERMISSION_CACHE.put(methodKey, dataPermission == null ? EMPTY_DATA_PERMISSION : dataPermission); return dataPermission; diff --git a/ballcat-system/ballcat-system-controller/src/main/java/com/hccake/ballcat/system/controller/SysUserController.java b/ballcat-system/ballcat-system-controller/src/main/java/com/hccake/ballcat/system/controller/SysUserController.java index 726d01faa15b58eff7dc4702609d30a52ef4d2c1..a849c75909015bdf96acbbd076981923da231d7b 100644 --- a/ballcat-system/ballcat-system-controller/src/main/java/com/hccake/ballcat/system/controller/SysUserController.java +++ b/ballcat-system/ballcat-system-controller/src/main/java/com/hccake/ballcat/system/controller/SysUserController.java @@ -1,6 +1,7 @@ package com.hccake.ballcat.system.controller; import cn.hutool.core.collection.CollectionUtil; +import com.hccake.ballcat.common.log.access.annotation.AccessLogIgnore; import com.hccake.ballcat.common.log.operation.annotation.CreateOperationLogging; import com.hccake.ballcat.common.log.operation.annotation.DeleteOperationLogging; import com.hccake.ballcat.common.log.operation.annotation.UpdateOperationLogging; @@ -186,6 +187,7 @@ public class SysUserController { /** * 修改用户密码 */ + @AccessLogIgnore(req = true) @PutMapping("/pass/{userId}") @ApiOperation(value = "修改系统用户密码", notes = "修改系统用户密码") @UpdateOperationLogging(msg = "修改系统用户密码")