From c16874a17b00d78825b8052804b295b4d85f99b9 Mon Sep 17 00:00:00 2001 From: lijiahang Date: Fri, 30 Jun 2023 14:37:52 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E8=84=B1=E6=95=8F=E7=AD=96?= =?UTF-8?q?=E7=95=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/annotation/Desensitize.java | 6 +- ...esensitize.java => DesensitizeObject.java} | 7 +- .../constant/ResponseAdviceOrderConst.java | 4 +- .../OrionDesensitizeAutoConfiguration.java | 34 +++++- .../DesensitizeValueSerializeFilter.java | 102 ++++++++++++++++++ .../handler/DesensitizeResultHandler.java | 50 --------- .../core/processor/IDesensitizeProcessor.java | 19 ---- .../processor/ObjectDesensitizeProcessor.java | 78 -------------- .../WrapperDesensitizeProcessor.java | 26 ----- .../web/config/OrionWebAutoConfiguration.java | 18 +++- 10 files changed, 152 insertions(+), 192 deletions(-) rename orion-ops-framework/orion-ops-common/src/main/java/com/orion/ops/framework/common/annotation/{DoDesensitize.java => DesensitizeObject.java} (58%) create mode 100644 orion-ops-framework/orion-ops-spring-boot-starter-desensitize/src/main/java/com/orion/ops/framework/desensitize/core/filter/DesensitizeValueSerializeFilter.java delete mode 100644 orion-ops-framework/orion-ops-spring-boot-starter-desensitize/src/main/java/com/orion/ops/framework/desensitize/core/handler/DesensitizeResultHandler.java delete mode 100644 orion-ops-framework/orion-ops-spring-boot-starter-desensitize/src/main/java/com/orion/ops/framework/desensitize/core/processor/IDesensitizeProcessor.java delete mode 100644 orion-ops-framework/orion-ops-spring-boot-starter-desensitize/src/main/java/com/orion/ops/framework/desensitize/core/processor/ObjectDesensitizeProcessor.java delete mode 100644 orion-ops-framework/orion-ops-spring-boot-starter-desensitize/src/main/java/com/orion/ops/framework/desensitize/core/processor/WrapperDesensitizeProcessor.java diff --git a/orion-ops-framework/orion-ops-common/src/main/java/com/orion/ops/framework/common/annotation/Desensitize.java b/orion-ops-framework/orion-ops-common/src/main/java/com/orion/ops/framework/common/annotation/Desensitize.java index 25b57cd0..c112f322 100644 --- a/orion-ops-framework/orion-ops-common/src/main/java/com/orion/ops/framework/common/annotation/Desensitize.java +++ b/orion-ops-framework/orion-ops-common/src/main/java/com/orion/ops/framework/common/annotation/Desensitize.java @@ -5,7 +5,7 @@ import java.lang.annotation.*; /** * 脱敏配置元注解 *

- * 标注在字段上则标记脱敏配置 + * 标注在字段上则标记该字段执行 http 序列化时脱敏 * * @author Jiahang Li * @version 1.0.0 @@ -19,12 +19,12 @@ public @interface Desensitize { /** * @return 起始保留字符数 */ - int keepStart() default 0; + int keepStart() default 1; /** * @return 结束保留字符数 */ - int keepEnd() default 0; + int keepEnd() default 1; /** * @return 脱敏字符 diff --git a/orion-ops-framework/orion-ops-common/src/main/java/com/orion/ops/framework/common/annotation/DoDesensitize.java b/orion-ops-framework/orion-ops-common/src/main/java/com/orion/ops/framework/common/annotation/DesensitizeObject.java similarity index 58% rename from orion-ops-framework/orion-ops-common/src/main/java/com/orion/ops/framework/common/annotation/DoDesensitize.java rename to orion-ops-framework/orion-ops-common/src/main/java/com/orion/ops/framework/common/annotation/DesensitizeObject.java index ea8401c6..86d84269 100644 --- a/orion-ops-framework/orion-ops-common/src/main/java/com/orion/ops/framework/common/annotation/DoDesensitize.java +++ b/orion-ops-framework/orion-ops-common/src/main/java/com/orion/ops/framework/common/annotation/DesensitizeObject.java @@ -5,16 +5,15 @@ import java.lang.annotation.*; /** * 脱敏配置元注解 *

- * 标注在方法上则标记过滤开启 - * 多层对象脱敏需要在字段上标注 + * 标注在类上则标记该类执行序列化时会执行脱敏 * * @author Jiahang Li * @version 1.0.0 * @since 2023/6/29 16:58 */ -@Target({ElementType.METHOD, ElementType.FIELD}) +@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented -public @interface DoDesensitize { +public @interface DesensitizeObject { } diff --git a/orion-ops-framework/orion-ops-common/src/main/java/com/orion/ops/framework/common/constant/ResponseAdviceOrderConst.java b/orion-ops-framework/orion-ops-common/src/main/java/com/orion/ops/framework/common/constant/ResponseAdviceOrderConst.java index 047a9699..78db9976 100644 --- a/orion-ops-framework/orion-ops-common/src/main/java/com/orion/ops/framework/common/constant/ResponseAdviceOrderConst.java +++ b/orion-ops-framework/orion-ops-common/src/main/java/com/orion/ops/framework/common/constant/ResponseAdviceOrderConst.java @@ -9,8 +9,6 @@ package com.orion.ops.framework.common.constant; */ public interface ResponseAdviceOrderConst { - int DESENSITIZE = Integer.MIN_VALUE + 2000; - - int WRAPPER = Integer.MIN_VALUE + 3000; + int WRAPPER = Integer.MIN_VALUE + 1000; } diff --git a/orion-ops-framework/orion-ops-spring-boot-starter-desensitize/src/main/java/com/orion/ops/framework/desensitize/config/OrionDesensitizeAutoConfiguration.java b/orion-ops-framework/orion-ops-spring-boot-starter-desensitize/src/main/java/com/orion/ops/framework/desensitize/config/OrionDesensitizeAutoConfiguration.java index 4cd6d2cb..dc7820bd 100644 --- a/orion-ops-framework/orion-ops-spring-boot-starter-desensitize/src/main/java/com/orion/ops/framework/desensitize/config/OrionDesensitizeAutoConfiguration.java +++ b/orion-ops-framework/orion-ops-spring-boot-starter-desensitize/src/main/java/com/orion/ops/framework/desensitize/config/OrionDesensitizeAutoConfiguration.java @@ -1,25 +1,51 @@ package com.orion.ops.framework.desensitize.config; -import com.orion.ops.framework.desensitize.core.handler.DesensitizeResultHandler; +import com.alibaba.fastjson.serializer.SerializeFilter; +import com.alibaba.fastjson.support.config.FastJsonConfig; +import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter; +import com.orion.lang.utils.Arrays1; +import com.orion.ops.framework.desensitize.core.filter.DesensitizeValueSerializeFilter; import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.AutoConfigureAfter; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.context.annotation.Bean; /** * 数据脱敏置类 + *

+ * 前置需要装配 orion-ops-spring-boot-starter-web * * @author Jiahang Li * @version 1.0.0 * @since 2023/6/29 16:55 */ @AutoConfiguration +@AutoConfigureAfter(name = "com.orion.ops.framework.web.config.OrionWebAutoConfiguration") public class OrionDesensitizeAutoConfiguration { /** - * @return 返回结果脱敏处理器 + * @return 返回 序列化脱敏过滤器 */ @Bean - public DesensitizeResultHandler desensitizeResultHandler() { - return new DesensitizeResultHandler(); + @ConditionalOnBean(FastJsonHttpMessageConverter.class) + public DesensitizeValueSerializeFilter desensitizeResultHandler(FastJsonHttpMessageConverter converter) { + DesensitizeValueSerializeFilter desensitizeFilter = new DesensitizeValueSerializeFilter(); + // 获取 json 配置 + FastJsonConfig config = converter.getFastJsonConfig(); + SerializeFilter[] filters = config.getSerializeFilters(); + int filterLength = Arrays1.length(filters); + if (filterLength == 0) { + // 未设置配置 + filters = new SerializeFilter[]{desensitizeFilter}; + } else { + SerializeFilter[] newFilters = new SerializeFilter[filterLength + 1]; + System.arraycopy(filters, 0, newFilters, 0, filterLength); + newFilters[filterLength] = desensitizeFilter; + filters = newFilters; + } + // 更新到配置 + config.setSerializeFilters(filters); + return desensitizeFilter; } } diff --git a/orion-ops-framework/orion-ops-spring-boot-starter-desensitize/src/main/java/com/orion/ops/framework/desensitize/core/filter/DesensitizeValueSerializeFilter.java b/orion-ops-framework/orion-ops-spring-boot-starter-desensitize/src/main/java/com/orion/ops/framework/desensitize/core/filter/DesensitizeValueSerializeFilter.java new file mode 100644 index 00000000..deb6163f --- /dev/null +++ b/orion-ops-framework/orion-ops-spring-boot-starter-desensitize/src/main/java/com/orion/ops/framework/desensitize/core/filter/DesensitizeValueSerializeFilter.java @@ -0,0 +1,102 @@ +package com.orion.ops.framework.desensitize.core.filter; + +import com.alibaba.fastjson.annotation.JSONField; +import com.alibaba.fastjson.serializer.ValueFilter; +import com.orion.lang.utils.Objects1; +import com.orion.lang.utils.Strings; +import com.orion.lang.utils.collect.Maps; +import com.orion.lang.utils.reflect.Annotations; +import com.orion.lang.utils.reflect.Fields; +import com.orion.ops.framework.common.annotation.Desensitize; +import com.orion.ops.framework.common.annotation.DesensitizeObject; +import com.orion.ops.framework.common.utils.Desensitizes; + +import java.lang.reflect.Field; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 脱敏序列化器 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2023/6/30 12:19 + */ +public class DesensitizeValueSerializeFilter implements ValueFilter { + + private static final Map> DESENSITIZE_FIELDS = new HashMap<>(); + + @Override + public Object process(Object object, String name, Object value) { + if (object == null || value == null) { + return value; + } + Desensitize config = doDesensitizeField(object, name); + // 无需脱敏 + if (config == null) { + return value; + } + // 脱敏 + return Desensitizes.mix(Objects1.toString(value), config.keepStart(), config.keepEnd(), config.replacer()); + } + + /** + * 是否要执行脱敏 + * + * @param object object + * @param name name + * @return 是否执行 + */ + private Desensitize doDesensitizeField(Object object, String name) { + // 查询缓存 + String className = object.getClass().toString(); + Map fields = DESENSITIZE_FIELDS.get(className); + if (fields == null) { + // 查询脱敏配置 + fields = this.initClassDesensitize(object); + DESENSITIZE_FIELDS.put(className, fields); + } + // 无需脱敏 + if (fields.isEmpty()) { + return null; + } + return fields.get(name); + } + + /** + * 初始化脱敏配置 + * + * @param object object + * @return config + */ + private Map initClassDesensitize(Object object) { + Class dataClass = object.getClass(); + // 检查是否为脱敏对象 + DesensitizeObject has = Annotations.getAnnotation(dataClass, DesensitizeObject.class); + if (has == null) { + return Maps.empty(); + } + Map config = new HashMap<>(); + // 获取对象字段 + List fields = Fields.getFields(dataClass); + // 查询脱敏配置 + for (Field field : fields) { + // 脱敏注解 + Desensitize desensitize = Annotations.getAnnotation(field, Desensitize.class); + if (desensitize == null) { + continue; + } + // json 注解 + JSONField jsonField = Annotations.getAnnotation(field, JSONField.class); + String fieldName = field.getName(); + String jsonFieldName; + if (jsonField != null && !Strings.isBlank(jsonFieldName = jsonField.name())) { + fieldName = jsonFieldName; + } + config.put(fieldName, desensitize); + } + return config; + } + +} diff --git a/orion-ops-framework/orion-ops-spring-boot-starter-desensitize/src/main/java/com/orion/ops/framework/desensitize/core/handler/DesensitizeResultHandler.java b/orion-ops-framework/orion-ops-spring-boot-starter-desensitize/src/main/java/com/orion/ops/framework/desensitize/core/handler/DesensitizeResultHandler.java deleted file mode 100644 index 2af038f6..00000000 --- a/orion-ops-framework/orion-ops-spring-boot-starter-desensitize/src/main/java/com/orion/ops/framework/desensitize/core/handler/DesensitizeResultHandler.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.orion.ops.framework.desensitize.core.handler; - -import com.orion.lang.define.wrapper.Wrapper; -import com.orion.ops.framework.common.constant.ResponseAdviceOrderConst; -import com.orion.ops.framework.common.annotation.DoDesensitize; -import com.orion.ops.framework.desensitize.core.processor.IDesensitizeProcessor; -import com.orion.ops.framework.desensitize.core.processor.ObjectDesensitizeProcessor; -import com.orion.ops.framework.desensitize.core.processor.WrapperDesensitizeProcessor; -import org.jetbrains.annotations.NotNull; -import org.springframework.core.MethodParameter; -import org.springframework.core.annotation.Order; -import org.springframework.http.MediaType; -import org.springframework.http.server.ServerHttpRequest; -import org.springframework.http.server.ServerHttpResponse; -import org.springframework.web.bind.annotation.ControllerAdvice; -import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice; - -/** - * 返回结果脱敏处理器 - * - * @author Jiahang Li - * @version 1.0.0 - * @since 2023/6/15 17:38 - */ -@Order(ResponseAdviceOrderConst.DESENSITIZE) -@ControllerAdvice -public class DesensitizeResultHandler implements ResponseBodyAdvice { - - @Override - public boolean supports(MethodParameter methodParameter, @NotNull Class converterType) { - return methodParameter.hasMethodAnnotation(DoDesensitize.class); - } - - @Override - public Object beforeBodyWrite(Object body, @NotNull MethodParameter methodParameter, @NotNull MediaType selectedContentType, @NotNull Class selectedConverterType, - @NotNull ServerHttpRequest request, @NotNull ServerHttpResponse response) { - IDesensitizeProcessor processor; - if (body instanceof Wrapper) { - // wrapper - processor = new WrapperDesensitizeProcessor(); - } else { - // 普通对象 - processor = new ObjectDesensitizeProcessor(); - } - // 执行脱敏 - processor.execute(body); - return body; - } - -} diff --git a/orion-ops-framework/orion-ops-spring-boot-starter-desensitize/src/main/java/com/orion/ops/framework/desensitize/core/processor/IDesensitizeProcessor.java b/orion-ops-framework/orion-ops-spring-boot-starter-desensitize/src/main/java/com/orion/ops/framework/desensitize/core/processor/IDesensitizeProcessor.java deleted file mode 100644 index 09ca6ad0..00000000 --- a/orion-ops-framework/orion-ops-spring-boot-starter-desensitize/src/main/java/com/orion/ops/framework/desensitize/core/processor/IDesensitizeProcessor.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.orion.ops.framework.desensitize.core.processor; - -/** - * 脱敏处理器 - * - * @author Jiahang Li - * @version 1.0.0 - * @since 2023/6/29 17:50 - */ -public interface IDesensitizeProcessor { - - /** - * 脱敏操作 - * - * @param data data - */ - void execute(T data); - -} diff --git a/orion-ops-framework/orion-ops-spring-boot-starter-desensitize/src/main/java/com/orion/ops/framework/desensitize/core/processor/ObjectDesensitizeProcessor.java b/orion-ops-framework/orion-ops-spring-boot-starter-desensitize/src/main/java/com/orion/ops/framework/desensitize/core/processor/ObjectDesensitizeProcessor.java deleted file mode 100644 index f882f4f4..00000000 --- a/orion-ops-framework/orion-ops-spring-boot-starter-desensitize/src/main/java/com/orion/ops/framework/desensitize/core/processor/ObjectDesensitizeProcessor.java +++ /dev/null @@ -1,78 +0,0 @@ -package com.orion.ops.framework.desensitize.core.processor; - -import com.orion.lang.utils.reflect.Annotations; -import com.orion.lang.utils.reflect.Methods; -import com.orion.ops.framework.common.utils.Desensitizes; -import com.orion.ops.framework.common.annotation.Desensitize; -import com.orion.ops.framework.common.annotation.DoDesensitize; - -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.util.Map; - -/** - * 对象脱敏处理器 - * - * @author Jiahang Li - * @version 1.0.0 - * @since 2023/6/29 17:21 - */ -public class ObjectDesensitizeProcessor implements IDesensitizeProcessor { - - @Override - public void execute(Object data) { - if (data == null) { - return; - } - Class dataClass = data.getClass(); - // 获取被标注脱敏的字段 - Map annotatedFields = Annotations.getAnnotatedFields(dataClass, Desensitize.class, true); - annotatedFields.forEach((f, d) -> { - // 获取 getter 方法 - Method getter = Methods.getGetterMethodByCache(dataClass, f.getName()); - if (!getter.getReturnType().equals(String.class)) { - // 非 string 不进行脱敏操作 - return; - } - // 调用 getter 方法 - String value = Methods.invokeMethod(data, getter); - if (value == null) { - // 为 null 不进行脱敏操作 - return; - } - // 数据脱敏 - String desensitizeValue = this.valueDesensitize(value, d); - // 获取 setter 方法 - Method setter = Methods.getSetterMethodByCache(dataClass, f.getName()); - // 调用 setter 方法 - Methods.invokeMethod(data, setter, desensitizeValue); - }); - // 获取被标注脱敏字段的对象 - Map annotatedObjects = Annotations.getAnnotatedFields(dataClass, DoDesensitize.class, true); - annotatedObjects.forEach((f, d) -> { - // 获取 getter 方法 - Method getter = Methods.getGetterMethodByCache(dataClass, f.getName()); - // 调用 getter 方法 - Object value = Methods.invokeMethod(data, getter); - if (value == null) { - // 为 null 不进行脱敏操作 - return; - } - // 执行对象脱敏操作 - this.execute(value); - }); - return; - } - - /** - * 数据脱敏 - * - * @param value value - * @param c 配置 - * @return 脱敏字符 - */ - private String valueDesensitize(String value, Desensitize c) { - return Desensitizes.mix(value, c.keepStart(), c.keepEnd(), c.replacer()); - } - -} diff --git a/orion-ops-framework/orion-ops-spring-boot-starter-desensitize/src/main/java/com/orion/ops/framework/desensitize/core/processor/WrapperDesensitizeProcessor.java b/orion-ops-framework/orion-ops-spring-boot-starter-desensitize/src/main/java/com/orion/ops/framework/desensitize/core/processor/WrapperDesensitizeProcessor.java deleted file mode 100644 index 9ec1c456..00000000 --- a/orion-ops-framework/orion-ops-spring-boot-starter-desensitize/src/main/java/com/orion/ops/framework/desensitize/core/processor/WrapperDesensitizeProcessor.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.orion.ops.framework.desensitize.core.processor; - -import com.orion.lang.define.wrapper.HttpWrapper; -import com.orion.lang.define.wrapper.RpcWrapper; - -/** - * wrapper 对象脱敏处理器 - * - * @author Jiahang Li - * @version 1.0.0 - * @since 2023/6/29 18:17 - */ -public class WrapperDesensitizeProcessor extends ObjectDesensitizeProcessor { - - @Override - public void execute(Object data) { - if (data instanceof HttpWrapper) { - super.execute(((HttpWrapper) data).getData()); - } else if (data instanceof RpcWrapper) { - super.execute(data); - } else { - super.execute(data); - } - } - -} diff --git a/orion-ops-framework/orion-ops-spring-boot-starter-web/src/main/java/com/orion/ops/framework/web/config/OrionWebAutoConfiguration.java b/orion-ops-framework/orion-ops-spring-boot-starter-web/src/main/java/com/orion/ops/framework/web/config/OrionWebAutoConfiguration.java index fe933f7f..5ae273cb 100644 --- a/orion-ops-framework/orion-ops-spring-boot-starter-web/src/main/java/com/orion/ops/framework/web/config/OrionWebAutoConfiguration.java +++ b/orion-ops-framework/orion-ops-spring-boot-starter-web/src/main/java/com/orion/ops/framework/web/config/OrionWebAutoConfiguration.java @@ -69,12 +69,12 @@ public class OrionWebAutoConfiguration implements WebMvcConfigurer { } /** - * @return http message 转换器 + * @return http message json 转换器 */ @Bean - public HttpMessageConverters fastJsonHttpMessageConverters() { + public FastJsonHttpMessageConverter fastJsonHttpMessageConverter() { // json 转换器 - FastJsonHttpMessageConverter jsonConverter = new FastJsonHttpMessageConverter(); + FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter(); // 配置 FastJsonConfig config = new FastJsonConfig(); // 支持的类型 @@ -86,7 +86,7 @@ public class OrionWebAutoConfiguration implements WebMvcConfigurer { MediaType.TEXT_HTML, MediaType.TEXT_XML ); - jsonConverter.setSupportedMediaTypes(mediaTypes); + converter.setSupportedMediaTypes(mediaTypes); // 序列化配置 config.setSerializerFeatures( SerializerFeature.DisableCircularReferenceDetect, @@ -94,7 +94,15 @@ public class OrionWebAutoConfiguration implements WebMvcConfigurer { SerializerFeature.WriteNullListAsEmpty, SerializerFeature.IgnoreNonFieldGetter ); - jsonConverter.setFastJsonConfig(config); + converter.setFastJsonConfig(config); + return converter; + } + + /** + * @return http message 转换器列表 + */ + @Bean + public HttpMessageConverters httpMessageConverters(FastJsonHttpMessageConverter jsonConverter) { // 先获取默认转换器 List> defaultConverters = new HttpMessageConverters().getConverters(); List> converters = new ArrayList<>();