commit baa1152da1371572b5d051499b2e22a34d74cdb1 Author: zweiandlen Date: Mon Oct 21 16:06:58 2024 +0800 init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3ff6177 --- /dev/null +++ b/.gitignore @@ -0,0 +1,50 @@ +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### Vue.js ### +.DS_Store +node_modules/ +dist/ +npm-debug.log* +yarn-debug.log* +yarn-error.log* +package-lock.json +tests/**/coverage/ + +# Editor directories and files +.vscode/ +.mvn/ +/src/main/resources/static/ +/files/ +*.suo +*.ntvs* +*.njsproj +*.sln \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..307929b --- /dev/null +++ b/README.md @@ -0,0 +1,7 @@ +# sensitive + +适用于 jackson 的脱敏处理 + +## 条件脱敏 + +实现 DesensitizedFilter 接口,定义脱敏条件。 \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..e50a134 --- /dev/null +++ b/pom.xml @@ -0,0 +1,55 @@ + + + 4.0.0 + + ltd.llvy + sensitive + 1.0-SNAPSHOT + + + 17 + 17 + UTF-8 + + + + + + com.fasterxml.jackson.core + jackson-core + 2.17.2 + + + + com.fasterxml.jackson.core + jackson-databind + 2.17.2 + + + + cn.hutool + hutool-core + 5.8.32 + + + + + + gitea + https://www.llvy.ltd/api/packages/llvy.ltd/maven + + + + + gitea + https://www.llvy.ltd/api/packages/llvy.ltd/maven + + + gitea + https://www.llvy.ltd/api/packages/llvy.ltd/maven + + + + \ No newline at end of file diff --git a/src/main/java/ltd/llvy/sensitive/annotation/Desensitization.java b/src/main/java/ltd/llvy/sensitive/annotation/Desensitization.java new file mode 100644 index 0000000..e6f708b --- /dev/null +++ b/src/main/java/ltd/llvy/sensitive/annotation/Desensitization.java @@ -0,0 +1,39 @@ +package ltd.llvy.sensitive.annotation; + +import cn.hutool.core.util.DesensitizedUtil; +import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import ltd.llvy.sensitive.filter.impl.DefaultDesensitizedFilter; +import ltd.llvy.sensitive.support.JsonDesensitizationSerializer; + +/** + * (Desensitization) 脱敏注解 + * + * @author zweiandlen + * @since 2024/9/27 14:32 + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.FIELD}) +@JacksonAnnotationsInside +@JsonSerialize(using = JsonDesensitizationSerializer.class) +public @interface Desensitization { + + /** + * 脱敏的类型:比如手机号、邮箱. + * + * @return 脱敏类型 + */ + DesensitizedUtil.DesensitizedType type() default + DesensitizedUtil.DesensitizedType.CLEAR_TO_EMPTY; + + /** + * 过滤的方法:自定义符合条件的脱敏数据. + * + * @return 过滤方法 + */ + Class filter() default DefaultDesensitizedFilter.class; +} diff --git a/src/main/java/ltd/llvy/sensitive/filter/DesensitizedFilter.java b/src/main/java/ltd/llvy/sensitive/filter/DesensitizedFilter.java new file mode 100644 index 0000000..32481b0 --- /dev/null +++ b/src/main/java/ltd/llvy/sensitive/filter/DesensitizedFilter.java @@ -0,0 +1,17 @@ +package ltd.llvy.sensitive.filter; + +/** + * (DesensitizedFilter) + * + * @author zweiandlen + * @since 2024/10/21 14:33 + */ +public interface DesensitizedFilter { + + /** + * 符合条件的明文,不符合的脱敏 + * + * @return 布尔值 + */ + boolean doFilter(); +} diff --git a/src/main/java/ltd/llvy/sensitive/filter/impl/DefaultDesensitizedFilter.java b/src/main/java/ltd/llvy/sensitive/filter/impl/DefaultDesensitizedFilter.java new file mode 100644 index 0000000..9b2c8bd --- /dev/null +++ b/src/main/java/ltd/llvy/sensitive/filter/impl/DefaultDesensitizedFilter.java @@ -0,0 +1,16 @@ +package ltd.llvy.sensitive.filter.impl; + +import ltd.llvy.sensitive.filter.DesensitizedFilter; + +/** + * (DefaultDesensitizedFilter) + * + * @author zweiandlen + * @since 2024/10/21 15:10 + */ +public class DefaultDesensitizedFilter implements DesensitizedFilter { + @Override + public boolean doFilter() { + return false; + } +} diff --git a/src/main/java/ltd/llvy/sensitive/support/JsonDesensitizationSerializer.java b/src/main/java/ltd/llvy/sensitive/support/JsonDesensitizationSerializer.java new file mode 100644 index 0000000..e0c160e --- /dev/null +++ b/src/main/java/ltd/llvy/sensitive/support/JsonDesensitizationSerializer.java @@ -0,0 +1,82 @@ +package ltd.llvy.sensitive.support; + +import cn.hutool.core.util.DesensitizedUtil; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.BeanProperty; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.ser.ContextualSerializer; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.util.Objects; + +import ltd.llvy.sensitive.annotation.Desensitization; +import ltd.llvy.sensitive.filter.DesensitizedFilter; + +/** + * (JsonDesensitizationSerializer) + * + * @author zweiandlen + * @since 2024/9/27 14:35 + */ +public class JsonDesensitizationSerializer extends JsonSerializer + implements ContextualSerializer { + + /** 脱敏字段类型 */ + private DesensitizedUtil.DesensitizedType type; + + /** 过滤方法. */ + private Class clazz; + + public JsonDesensitizationSerializer() {} + + public JsonDesensitizationSerializer(DesensitizedUtil.DesensitizedType type, Class clazz) { + this.type = type; + this.clazz = clazz; + } + + @Override + public void serialize( + String plaintext, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) + throws IOException { + String desensitize = DesensitizedUtil.desensitized(plaintext, type); + DesensitizedFilter filter = null; + try { + filter = (DesensitizedFilter) clazz.getConstructor().newInstance(); + } catch (InstantiationException + | IllegalAccessException + | InvocationTargetException + | NoSuchMethodException e) { + throw new RuntimeException(e); + } + // 符合过滤条件的显示明文,不符合的脱敏 + if (filter.doFilter()) { + jsonGenerator.writeString(plaintext); + } else { + jsonGenerator.writeString(desensitize); + } + } + + @Override + public JsonSerializer createContextual( + SerializerProvider serializerProvider, BeanProperty property) throws JsonMappingException { + if (property != null) { + // 判断是不是String类型的参数 + if (Objects.equals(property.getType().getRawClass(), String.class)) { + // 获取属性上面的注解 + Desensitization annotation = property.getAnnotation(Desensitization.class); + if (annotation == null) { + annotation = property.getContextAnnotation(Desensitization.class); + } + if (annotation != null) { + // 给当前属性赋值 + return new JsonDesensitizationSerializer(annotation.type(), annotation.filter()); + } + } + return serializerProvider.findValueSerializer(property.getType(), property); + } else { + return serializerProvider.findNullValueSerializer(null); + } + } +}