diff --git a/yudao-framework/yudao-spring-boot-starter-biz-desensitize/pom.xml b/yudao-framework/yudao-spring-boot-starter-biz-desensitize/pom.xml index 4119f8ea7..7f15d0d4c 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-desensitize/pom.xml +++ b/yudao-framework/yudao-spring-boot-starter-biz-desensitize/pom.xml @@ -4,9 +4,9 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - cn.iocoder.boot yudao-framework - 1.6.6-snapshot + cn.iocoder.boot + ${revision} yudao-spring-boot-starter-biz-desensitize @@ -22,5 +22,22 @@ cn.iocoder.boot yudao-common + + + + com.fasterxml.jackson.core + jackson-annotations + + + com.fasterxml.jackson.core + jackson-databind + + + + + cn.iocoder.boot + yudao-spring-boot-starter-test + test + \ No newline at end of file diff --git a/yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/annotation/Desensitize.java b/yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/annotation/Desensitize.java index bf0f585c4..65dd2108d 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/annotation/Desensitize.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/annotation/Desensitize.java @@ -1,7 +1,9 @@ package cn.iocoder.yudao.framework.desensitize.annotation; -import cn.iocoder.yudao.framework.desensitize.enums.DesensitizationStrategyEnum; import cn.iocoder.yudao.framework.desensitize.handler.DesensitizationHandler; +import cn.iocoder.yudao.framework.desensitize.serializer.StringDesensitizeSerializer; +import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; @@ -11,40 +13,18 @@ import java.lang.annotation.Target; /** - * Desensitize 注解配置会覆盖 DesensitizationStrategyEnum 配置 + * Desensitize 顶级脱敏注解 */ -@Target({ElementType.FIELD}) -@Retention(RetentionPolicy.RUNTIME) @Documented +@Target({ElementType.FIELD, ElementType.ANNOTATION_TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@JacksonAnnotationsInside +@JsonSerialize(using = StringDesensitizeSerializer.class) public @interface Desensitize { - /** - * 脱敏策略 - */ - DesensitizationStrategyEnum strategy(); - - /** - * 脱敏替换字符 - */ - String replacer(); - - /** - * 正则表达式 - */ - String regex(); - - /** - * 前缀保留长度 - */ - int preKeep(); - - /** - * 后缀保留长度 - */ - int suffixKeep(); - /** * 脱敏处理器 */ - Class handler(); + Class desensitizationHandler(); + } diff --git a/yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/annotation/RegexDesensitize.java b/yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/annotation/RegexDesensitize.java new file mode 100644 index 000000000..c2df586c4 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/annotation/RegexDesensitize.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.framework.desensitize.annotation; + +import cn.iocoder.yudao.framework.desensitize.handler.RegexDesensitizationHandler; +import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 正则脱敏注解 + */ +@Documented +@Target({ElementType.FIELD, ElementType.ANNOTATION_TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@JacksonAnnotationsInside +@Desensitize(desensitizationHandler = RegexDesensitizationHandler.class) +public @interface RegexDesensitize { + /** + * 匹配的正则表达式(默认匹配所有) + */ + String regex() default "^[\\s\\S]*$"; + + /** + * 替换规则,会将匹配到的字符串全部替换成 replacer + * 例如:regex=123; replacer=****** + * 原始字符串 123456789 + * 脱敏后字符串 ******456789 + */ + String replacer() default "******"; +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/annotation/SliderDesensitize.java b/yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/annotation/SliderDesensitize.java new file mode 100644 index 000000000..ebafaa9bc --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/annotation/SliderDesensitize.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.framework.desensitize.annotation; + +import cn.iocoder.yudao.framework.desensitize.handler.SliderDesensitizationHandler; +import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 滑动脱敏注解 + */ +@Documented +@Target({ElementType.FIELD, ElementType.ANNOTATION_TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@JacksonAnnotationsInside +@Desensitize(desensitizationHandler = SliderDesensitizationHandler.class) +public @interface SliderDesensitize { + + /** + * 后缀保留长度 + */ + int suffixKeep() default 0; + + /** + * 替换规则,会将前缀后缀保留后,全部替换成 replacer + * 例如:prefixKeep = 1; suffixKeep = 2; replacer = "*"; + * 原始字符串 123456 + * 脱敏后 1***56 + */ + String replacer() default "*"; + + /** + * 前缀保留长度 + */ + int prefixKeep() default 0; +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/annotation/constraints/BankCardDesensitize.java b/yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/annotation/constraints/BankCardDesensitize.java new file mode 100644 index 000000000..8fa73169a --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/annotation/constraints/BankCardDesensitize.java @@ -0,0 +1,21 @@ +package cn.iocoder.yudao.framework.desensitize.annotation.constraints; + +import cn.iocoder.yudao.framework.desensitize.annotation.SliderDesensitize; +import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 银行卡号 + */ +@Documented +@Target({ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +@JacksonAnnotationsInside +@SliderDesensitize(prefixKeep = 6, suffixKeep = 2, replacer = "*") // 银行卡号;比如:9988002866797031脱敏之后为998800********31 +public @interface BankCardDesensitize { +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/annotation/constraints/CarLicenseDesensitize.java b/yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/annotation/constraints/CarLicenseDesensitize.java new file mode 100644 index 000000000..11f1f5814 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/annotation/constraints/CarLicenseDesensitize.java @@ -0,0 +1,21 @@ +package cn.iocoder.yudao.framework.desensitize.annotation.constraints; + +import cn.iocoder.yudao.framework.desensitize.annotation.SliderDesensitize; +import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 车牌号 + */ +@Documented +@Target({ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +@JacksonAnnotationsInside +@SliderDesensitize(prefixKeep = 3, suffixKeep = 1, replacer = "*") // 车牌号;比如:粤A66666脱敏之后为粤A6***6 +public @interface CarLicenseDesensitize { +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/annotation/constraints/ChineseNameDesensitize.java b/yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/annotation/constraints/ChineseNameDesensitize.java new file mode 100644 index 000000000..97d2698ed --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/annotation/constraints/ChineseNameDesensitize.java @@ -0,0 +1,21 @@ +package cn.iocoder.yudao.framework.desensitize.annotation.constraints; + +import cn.iocoder.yudao.framework.desensitize.annotation.SliderDesensitize; +import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 中文名 + */ +@Documented +@Target({ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +@JacksonAnnotationsInside +@SliderDesensitize(prefixKeep = 1, suffixKeep = 0, replacer = "*") // 中文名;比如:刘子豪脱敏之后为刘** +public @interface ChineseNameDesensitize { +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/annotation/constraints/EmailDesensitize.java b/yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/annotation/constraints/EmailDesensitize.java new file mode 100644 index 000000000..142e7c0f6 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/annotation/constraints/EmailDesensitize.java @@ -0,0 +1,21 @@ +package cn.iocoder.yudao.framework.desensitize.annotation.constraints; + +import cn.iocoder.yudao.framework.desensitize.annotation.RegexDesensitize; +import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 邮箱 + */ +@Documented +@Target({ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +@JacksonAnnotationsInside +@RegexDesensitize(regex = "(^.)[^@]*(@.*$)", replacer ="$1****$2") // 邮箱;比如:example@gmail.com脱敏之后为e****@gmail.com +public @interface EmailDesensitize { +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/annotation/constraints/FixedPhoneDesensitize.java b/yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/annotation/constraints/FixedPhoneDesensitize.java new file mode 100644 index 000000000..f91988735 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/annotation/constraints/FixedPhoneDesensitize.java @@ -0,0 +1,21 @@ +package cn.iocoder.yudao.framework.desensitize.annotation.constraints; + +import cn.iocoder.yudao.framework.desensitize.annotation.SliderDesensitize; +import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 固定电话 + */ +@Documented +@Target({ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +@JacksonAnnotationsInside +@SliderDesensitize(prefixKeep = 4, suffixKeep = 2, replacer = "*") // 固定电话;比如:01086551122脱敏之后为0108*****22 +public @interface FixedPhoneDesensitize { +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/annotation/constraints/IdCardDesensitize.java b/yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/annotation/constraints/IdCardDesensitize.java new file mode 100644 index 000000000..921019c5d --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/annotation/constraints/IdCardDesensitize.java @@ -0,0 +1,21 @@ +package cn.iocoder.yudao.framework.desensitize.annotation.constraints; + +import cn.iocoder.yudao.framework.desensitize.annotation.SliderDesensitize; +import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 身份证 + */ +@Documented +@Target({ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +@JacksonAnnotationsInside +@SliderDesensitize(prefixKeep = 6, suffixKeep = 2, replacer = "*") // 身份证号码;比如:530321199204074611脱敏之后为530321**********11 +public @interface IdCardDesensitize { +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/annotation/constraints/PasswordDesensitize.java b/yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/annotation/constraints/PasswordDesensitize.java new file mode 100644 index 000000000..8d823a139 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/annotation/constraints/PasswordDesensitize.java @@ -0,0 +1,21 @@ +package cn.iocoder.yudao.framework.desensitize.annotation.constraints; + +import cn.iocoder.yudao.framework.desensitize.annotation.SliderDesensitize; +import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 密码 + */ +@Documented +@Target({ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +@JacksonAnnotationsInside +@SliderDesensitize(prefixKeep = 0, suffixKeep = 0, replacer = "*") // 密码;比如:123456脱敏之后为****** +public @interface PasswordDesensitize { +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/annotation/constraints/PhoneNumberDesensitize.java b/yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/annotation/constraints/PhoneNumberDesensitize.java new file mode 100644 index 000000000..0829c6a45 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/annotation/constraints/PhoneNumberDesensitize.java @@ -0,0 +1,21 @@ +package cn.iocoder.yudao.framework.desensitize.annotation.constraints; + +import cn.iocoder.yudao.framework.desensitize.annotation.SliderDesensitize; +import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 手机号 + */ +@Documented +@Target({ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +@JacksonAnnotationsInside +@SliderDesensitize(prefixKeep = 3, suffixKeep = 4, replacer = "*") // 手机号;比如:13248765917脱敏之后为132****5917 +public @interface PhoneNumberDesensitize { +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/constants/DesensitizeConstants.java b/yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/constants/DesensitizeConstants.java deleted file mode 100644 index f883173c3..000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/constants/DesensitizeConstants.java +++ /dev/null @@ -1,24 +0,0 @@ -package cn.iocoder.yudao.framework.desensitize.constants; - -import lombok.AccessLevel; -import lombok.NoArgsConstructor; - -@NoArgsConstructor(access = AccessLevel.PRIVATE) -public class DesensitizeConstants { - - /** - * 默认正则 - */ - public static final String DEFAULT_REGEX = null; - - /** - * 默认保持长度 - */ - public static final int DEFAULT_KEEP_LENGTH = -1; - - /** - * 默认替换字符 - */ - public static final String DEFAULT_REPLACER = "****"; - -} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/enums/DesensitizationStrategyEnum.java b/yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/enums/DesensitizationStrategyEnum.java deleted file mode 100644 index 89a1f63c8..000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/enums/DesensitizationStrategyEnum.java +++ /dev/null @@ -1,49 +0,0 @@ -package cn.iocoder.yudao.framework.desensitize.enums; - -import lombok.Getter; -import lombok.RequiredArgsConstructor; - -import static cn.iocoder.yudao.framework.desensitize.constants.DesensitizeConstants.DEFAULT_KEEP_LENGTH; -import static cn.iocoder.yudao.framework.desensitize.constants.DesensitizeConstants.DEFAULT_REGEX; -import static cn.iocoder.yudao.framework.desensitize.constants.DesensitizeConstants.DEFAULT_REPLACER; - -@Getter -@RequiredArgsConstructor -public enum DesensitizationStrategyEnum { - // 常用脱敏业务 - PHONE_NUMBER(DEFAULT_REGEX, 3, 4, DEFAULT_REPLACER), // 手机号;比如:13248765917脱敏之后为132****5917 - FIXED_PHONE(DEFAULT_REGEX, 4, 2, DEFAULT_REPLACER), // 固定电话;比如:01086551122脱敏之后为0108*****22 - ID_CARD(DEFAULT_REGEX, 6, 2, DEFAULT_REPLACER), // 身份证号码;比如:530321199204074611脱敏之后为530321**********11 - BANK_CARD(DEFAULT_REGEX, 6, 2, DEFAULT_REPLACER), // 银行卡号;比如:9988002866797031脱敏之后为998800********31 - CHINESE_NAME(DEFAULT_REGEX, 1, 0, "**"),// 中文名;比如:刘子豪脱敏之后为刘** - ADDRESS("[\\s\\S]+区", DEFAULT_KEEP_LENGTH, DEFAULT_KEEP_LENGTH, DEFAULT_REPLACER), // 地址只显示到地区,不显示详细地址;比如:广州市天河区幸福小区102号脱敏之后为广州市天河区******** - EMAIL("(^.)[^@]*(@.*$)", DEFAULT_KEEP_LENGTH, DEFAULT_KEEP_LENGTH, "$1****$2"), // 邮箱;比如:example@gmail.com脱敏之后为e******@gmail.com - CAR_LICENSE(DEFAULT_REGEX, 3, 1, DEFAULT_REPLACER), // 车牌号;比如:粤A66666脱敏之后为粤A6***6 - PASSWORD(DEFAULT_REGEX, 0, 0, DEFAULT_REPLACER), // 密码;比如:123456脱敏之后为****** - - // 自定义脱敏业务 - REGEX(DEFAULT_REGEX, DEFAULT_KEEP_LENGTH, DEFAULT_KEEP_LENGTH, DEFAULT_REPLACER), // 自定义正则表达式 - SLIDE(DEFAULT_REGEX, DEFAULT_KEEP_LENGTH, DEFAULT_KEEP_LENGTH, DEFAULT_REPLACER), // 滑动脱敏 - CUSTOM_HANDLE(DEFAULT_REGEX, DEFAULT_KEEP_LENGTH, DEFAULT_KEEP_LENGTH, DEFAULT_REPLACER); // 自定义处理器 - ; - - /** - * 正则表达式 - */ - private final String regex; - - /** - * 前缀保留长度 - */ - private final int preKeep; - - /** - * 后缀保留长度 - */ - private final int suffixKeep; - - /** - * 脱敏替换字符 - */ - private final String replacer; -} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/handler/DefaultDesensitizationHandler.java b/yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/handler/DefaultDesensitizationHandler.java deleted file mode 100644 index 4f8883c50..000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/handler/DefaultDesensitizationHandler.java +++ /dev/null @@ -1,10 +0,0 @@ -package cn.iocoder.yudao.framework.desensitize.handler; - -public class DefaultDesensitizationHandler implements DesensitizationHandler { - - @Override - public String handle(String origin) { - return origin; - } - -} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/handler/DesensitizationHandler.java b/yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/handler/DesensitizationHandler.java index d718aae1b..a5d06feb1 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/handler/DesensitizationHandler.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/handler/DesensitizationHandler.java @@ -8,6 +8,6 @@ public interface DesensitizationHandler { * @param origin 原始字符串 * @return 脱敏后的字符串 */ - String handle(String origin); + String desensitize(String origin, Object... arg); } diff --git a/yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/handler/DesensitizationHandlerHolder.java b/yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/handler/DesensitizationHandlerHolder.java new file mode 100644 index 000000000..23336b0cf --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/handler/DesensitizationHandlerHolder.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.framework.desensitize.handler; + +import cn.hutool.core.util.ReflectUtil; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +public class DesensitizationHandlerHolder { + /** + * handler 缓存,默认初始化内置的处理器 + */ + private static final Map, DesensitizationHandler> HANDLER_MAP = new ConcurrentHashMap<>() {{ + put(RegexDesensitizationHandler.class, new RegexDesensitizationHandler()); + put(SliderDesensitizationHandler.class, new SliderDesensitizationHandler()); + }}; + + public static DesensitizationHandler getDesensitizationHandler(Class clazz) { + DesensitizationHandler handler = HANDLER_MAP.get(clazz); + if (handler != null) { + return handler; + } + synchronized (DesensitizationHandlerHolder.class) { + handler = HANDLER_MAP.get(clazz); + // 双重校验锁 + if (handler != null) { + return handler; + } + handler = ReflectUtil.newInstanceIfPossible(clazz); + HANDLER_MAP.put(clazz, handler); + } + return handler; + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/handler/RegexDesensitizationHandler.java b/yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/handler/RegexDesensitizationHandler.java new file mode 100644 index 000000000..1846156d4 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/handler/RegexDesensitizationHandler.java @@ -0,0 +1,13 @@ +package cn.iocoder.yudao.framework.desensitize.handler; + +public class RegexDesensitizationHandler implements DesensitizationHandler { + + @Override + public String desensitize(String origin, Object... arg) { + String regex = (String) arg[0]; + String replacer = (String) arg[1]; + + return origin.replaceAll(regex, replacer); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/handler/SliderDesensitizationHandler.java b/yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/handler/SliderDesensitizationHandler.java new file mode 100644 index 000000000..81b9ccc50 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/handler/SliderDesensitizationHandler.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.framework.desensitize.handler; + +public class SliderDesensitizationHandler implements DesensitizationHandler { + + @Override + public String desensitize(String origin, Object... arg) { + int prefixKeep = (Integer) arg[0]; + int suffixKeep = (Integer) arg[1]; + String replacer = (String) arg[2]; + + int length = origin.length(); + + // 原始字符串长度小于等于保留长度,则原始字符串全部替换 + if (prefixKeep >= length || suffixKeep >= length) { + return buildReplacerByLength(replacer, length); + } + + // 如果原始字符串小于等于前后缀保留字符串长度,则原始字符串全部替换 + if ((prefixKeep + suffixKeep) >= length) { + return buildReplacerByLength(replacer, length); + } + + int interval = length - prefixKeep - suffixKeep; + return origin.substring(0, prefixKeep) + + buildReplacerByLength(replacer, interval) + + origin.substring(prefixKeep + interval); + } + + /** + * 根据长度循环构建替换符 + * + * @param replacer 替换符 + * @param length 长度 + * @return 构建后的替换符 + */ + private String buildReplacerByLength(String replacer, int length) { + return String.valueOf(replacer).repeat(Math.max(0, length)); + } +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/serializer/StringDesensitizeSerializer.java b/yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/serializer/StringDesensitizeSerializer.java new file mode 100644 index 000000000..a43b3e28e --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/serializer/StringDesensitizeSerializer.java @@ -0,0 +1,76 @@ +package cn.iocoder.yudao.framework.desensitize.serializer; + +import cn.hutool.core.util.ReflectUtil; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.desensitize.annotation.Desensitize; +import cn.iocoder.yudao.framework.desensitize.annotation.RegexDesensitize; +import cn.iocoder.yudao.framework.desensitize.annotation.SliderDesensitize; +import cn.iocoder.yudao.framework.desensitize.handler.DesensitizationHandler; +import cn.iocoder.yudao.framework.desensitize.handler.DesensitizationHandlerHolder; +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 com.fasterxml.jackson.databind.ser.std.StdSerializer; + +import java.io.IOException; +import java.lang.reflect.Field; + +/** + * 脱敏序列化器 + */ +public class StringDesensitizeSerializer extends StdSerializer implements ContextualSerializer { + private final DesensitizationHandler desensitizationHandler; + + protected StringDesensitizeSerializer(DesensitizationHandler desensitizationHandler) { + super(String.class); + this.desensitizationHandler = desensitizationHandler; + } + + + @Override + public JsonSerializer createContextual(SerializerProvider serializerProvider, BeanProperty beanProperty) throws JsonMappingException { + Desensitize annotation = beanProperty.getAnnotation(Desensitize.class); + if (annotation == null) { + return this; + } + + return new StringDesensitizeSerializer(DesensitizationHandlerHolder.getDesensitizationHandler(annotation.desensitizationHandler())); + } + + @Override + public void serialize(String value, JsonGenerator gen, SerializerProvider serializerProvider) throws IOException { + if (StrUtil.isBlank(value)) { + gen.writeNull(); + return; + } + + String currentName = gen.getOutputContext().getCurrentName(); + Object currentValue = gen.getCurrentValue(); + Class currentValueClass = currentValue.getClass(); + Field field = ReflectUtil.getField(currentValueClass, currentName); + + // 滑动处理器 + SliderDesensitize sliderDesensitize = field.getAnnotation(SliderDesensitize.class); + if (sliderDesensitize != null) { + value = this.desensitizationHandler.desensitize(value, sliderDesensitize.prefixKeep(), sliderDesensitize.suffixKeep(), sliderDesensitize.replacer()); + } + + // 正则处理器 + RegexDesensitize regexDesensitize = field.getAnnotation(RegexDesensitize.class); + if (regexDesensitize != null) { + value = this.desensitizationHandler.desensitize(value, regexDesensitize.regex(), regexDesensitize.replacer()); + } + + // 自定义处理器 + Desensitize desensitize = field.getAnnotation(Desensitize.class); + if (desensitize != null) { + value = this.desensitizationHandler.desensitize(value); + } + + gen.writeString(value); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/test/java/cn/iocoder/yudao/framework/desensitize/handler/DesensitizationHandlerTest.java b/yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/test/java/cn/iocoder/yudao/framework/desensitize/handler/DesensitizationHandlerTest.java new file mode 100644 index 000000000..63b4eaabf --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/test/java/cn/iocoder/yudao/framework/desensitize/handler/DesensitizationHandlerTest.java @@ -0,0 +1,25 @@ +package cn.iocoder.yudao.framework.desensitize.handler; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class DesensitizationHandlerTest { + + @Test + public void testSliderDesensitizationHandler() { + DesensitizationHandler handler = DesensitizationHandlerHolder.getDesensitizationHandler(SliderDesensitizationHandler.class); + + Assertions.assertEquals("A****FG", handler.desensitize("ABCDEFG", 1, 2, "*")); + Assertions.assertEquals("芋**码", handler.desensitize("芋道源码", 1, 1, "*")); + Assertions.assertEquals("****", handler.desensitize("芋道源码", 4, 0, "*")); + } + + @Test + public void testRegexDesensitizationHandler() { + DesensitizationHandler handler = DesensitizationHandlerHolder.getDesensitizationHandler(RegexDesensitizationHandler.class); + + Assertions.assertEquals("e****@gmail.com", handler.desensitize("example@gmail.com", "(^.)[^@]*(@.*$)", "$1****$2")); + Assertions.assertEquals("***,铁***", handler.desensitize("他妈的,铁废物", "他妈的|去你大爷|卧槽|草泥马|废物", "***")); + } + +}