Commit 5c8e41b84791cf92cc45896071a6b96b49ba20e3

Authored by gaibu
1 parent e637bff8

feat: 支持 vo 返回的脱敏

Showing 20 changed files with 450 additions and 109 deletions
yudao-framework/yudao-spring-boot-starter-biz-desensitize/pom.xml
@@ -4,9 +4,9 @@ @@ -4,9 +4,9 @@
4 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5 <modelVersion>4.0.0</modelVersion> 5 <modelVersion>4.0.0</modelVersion>
6 <parent> 6 <parent>
7 - <groupId>cn.iocoder.boot</groupId>  
8 <artifactId>yudao-framework</artifactId> 7 <artifactId>yudao-framework</artifactId>
9 - <version>1.6.6-snapshot</version> 8 + <groupId>cn.iocoder.boot</groupId>
  9 + <version>${revision}</version>
10 </parent> 10 </parent>
11 11
12 <artifactId>yudao-spring-boot-starter-biz-desensitize</artifactId> 12 <artifactId>yudao-spring-boot-starter-biz-desensitize</artifactId>
@@ -22,5 +22,22 @@ @@ -22,5 +22,22 @@
22 <groupId>cn.iocoder.boot</groupId> 22 <groupId>cn.iocoder.boot</groupId>
23 <artifactId>yudao-common</artifactId> 23 <artifactId>yudao-common</artifactId>
24 </dependency> 24 </dependency>
  25 +
  26 + <!-- jackson -->
  27 + <dependency>
  28 + <groupId>com.fasterxml.jackson.core</groupId>
  29 + <artifactId>jackson-annotations</artifactId>
  30 + </dependency>
  31 + <dependency>
  32 + <groupId>com.fasterxml.jackson.core</groupId>
  33 + <artifactId>jackson-databind</artifactId>
  34 + </dependency>
  35 +
  36 + <!-- Test 测试相关 -->
  37 + <dependency>
  38 + <groupId>cn.iocoder.boot</groupId>
  39 + <artifactId>yudao-spring-boot-starter-test</artifactId>
  40 + <scope>test</scope>
  41 + </dependency>
25 </dependencies> 42 </dependencies>
26 </project> 43 </project>
27 \ No newline at end of file 44 \ No newline at end of file
yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/annotation/Desensitize.java
1 package cn.iocoder.yudao.framework.desensitize.annotation; 1 package cn.iocoder.yudao.framework.desensitize.annotation;
2 2
3 -import cn.iocoder.yudao.framework.desensitize.enums.DesensitizationStrategyEnum;  
4 import cn.iocoder.yudao.framework.desensitize.handler.DesensitizationHandler; 3 import cn.iocoder.yudao.framework.desensitize.handler.DesensitizationHandler;
  4 +import cn.iocoder.yudao.framework.desensitize.serializer.StringDesensitizeSerializer;
  5 +import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
  6 +import com.fasterxml.jackson.databind.annotation.JsonSerialize;
5 7
6 import java.lang.annotation.Documented; 8 import java.lang.annotation.Documented;
7 import java.lang.annotation.ElementType; 9 import java.lang.annotation.ElementType;
@@ -11,40 +13,18 @@ import java.lang.annotation.Target; @@ -11,40 +13,18 @@ import java.lang.annotation.Target;
11 13
12 14
13 /** 15 /**
14 - * Desensitize 注解配置会覆盖 DesensitizationStrategyEnum 配置 16 + * Desensitize 顶级脱敏注解
15 */ 17 */
16 -@Target({ElementType.FIELD})  
17 -@Retention(RetentionPolicy.RUNTIME)  
18 @Documented 18 @Documented
  19 +@Target({ElementType.FIELD, ElementType.ANNOTATION_TYPE})
  20 +@Retention(RetentionPolicy.RUNTIME)
  21 +@JacksonAnnotationsInside
  22 +@JsonSerialize(using = StringDesensitizeSerializer.class)
19 public @interface Desensitize { 23 public @interface Desensitize {
20 24
21 /** 25 /**
22 - * 脱敏策略  
23 - */  
24 - DesensitizationStrategyEnum strategy();  
25 -  
26 - /**  
27 - * 脱敏替换字符  
28 - */  
29 - String replacer();  
30 -  
31 - /**  
32 - * 正则表达式  
33 - */  
34 - String regex();  
35 -  
36 - /**  
37 - * 前缀保留长度  
38 - */  
39 - int preKeep();  
40 -  
41 - /**  
42 - * 后缀保留长度  
43 - */  
44 - int suffixKeep();  
45 -  
46 - /**  
47 * 脱敏处理器 26 * 脱敏处理器
48 */ 27 */
49 - Class<? extends DesensitizationHandler> handler(); 28 + Class<? extends DesensitizationHandler> desensitizationHandler();
  29 +
50 } 30 }
yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/annotation/RegexDesensitize.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.desensitize.annotation;
  2 +
  3 +import cn.iocoder.yudao.framework.desensitize.handler.RegexDesensitizationHandler;
  4 +import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
  5 +
  6 +import java.lang.annotation.Documented;
  7 +import java.lang.annotation.ElementType;
  8 +import java.lang.annotation.Retention;
  9 +import java.lang.annotation.RetentionPolicy;
  10 +import java.lang.annotation.Target;
  11 +
  12 +/**
  13 + * 正则脱敏注解
  14 + */
  15 +@Documented
  16 +@Target({ElementType.FIELD, ElementType.ANNOTATION_TYPE})
  17 +@Retention(RetentionPolicy.RUNTIME)
  18 +@JacksonAnnotationsInside
  19 +@Desensitize(desensitizationHandler = RegexDesensitizationHandler.class)
  20 +public @interface RegexDesensitize {
  21 + /**
  22 + * 匹配的正则表达式(默认匹配所有)
  23 + */
  24 + String regex() default "^[\\s\\S]*$";
  25 +
  26 + /**
  27 + * 替换规则,会将匹配到的字符串全部替换成 replacer
  28 + * 例如:regex=123; replacer=******
  29 + * 原始字符串 123456789
  30 + * 脱敏后字符串 ******456789
  31 + */
  32 + String replacer() default "******";
  33 +}
yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/annotation/SliderDesensitize.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.desensitize.annotation;
  2 +
  3 +import cn.iocoder.yudao.framework.desensitize.handler.SliderDesensitizationHandler;
  4 +import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
  5 +
  6 +import java.lang.annotation.Documented;
  7 +import java.lang.annotation.ElementType;
  8 +import java.lang.annotation.Retention;
  9 +import java.lang.annotation.RetentionPolicy;
  10 +import java.lang.annotation.Target;
  11 +
  12 +/**
  13 + * 滑动脱敏注解
  14 + */
  15 +@Documented
  16 +@Target({ElementType.FIELD, ElementType.ANNOTATION_TYPE})
  17 +@Retention(RetentionPolicy.RUNTIME)
  18 +@JacksonAnnotationsInside
  19 +@Desensitize(desensitizationHandler = SliderDesensitizationHandler.class)
  20 +public @interface SliderDesensitize {
  21 +
  22 + /**
  23 + * 后缀保留长度
  24 + */
  25 + int suffixKeep() default 0;
  26 +
  27 + /**
  28 + * 替换规则,会将前缀后缀保留后,全部替换成 replacer
  29 + * 例如:prefixKeep = 1; suffixKeep = 2; replacer = "*";
  30 + * 原始字符串 123456
  31 + * 脱敏后 1***56
  32 + */
  33 + String replacer() default "*";
  34 +
  35 + /**
  36 + * 前缀保留长度
  37 + */
  38 + int prefixKeep() default 0;
  39 +}
yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/annotation/constraints/BankCardDesensitize.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.desensitize.annotation.constraints;
  2 +
  3 +import cn.iocoder.yudao.framework.desensitize.annotation.SliderDesensitize;
  4 +import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
  5 +
  6 +import java.lang.annotation.Documented;
  7 +import java.lang.annotation.ElementType;
  8 +import java.lang.annotation.Retention;
  9 +import java.lang.annotation.RetentionPolicy;
  10 +import java.lang.annotation.Target;
  11 +
  12 +/**
  13 + * 银行卡号
  14 + */
  15 +@Documented
  16 +@Target({ElementType.FIELD})
  17 +@Retention(RetentionPolicy.RUNTIME)
  18 +@JacksonAnnotationsInside
  19 +@SliderDesensitize(prefixKeep = 6, suffixKeep = 2, replacer = "*") // 银行卡号;比如:9988002866797031脱敏之后为998800********31
  20 +public @interface BankCardDesensitize {
  21 +}
yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/annotation/constraints/CarLicenseDesensitize.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.desensitize.annotation.constraints;
  2 +
  3 +import cn.iocoder.yudao.framework.desensitize.annotation.SliderDesensitize;
  4 +import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
  5 +
  6 +import java.lang.annotation.Documented;
  7 +import java.lang.annotation.ElementType;
  8 +import java.lang.annotation.Retention;
  9 +import java.lang.annotation.RetentionPolicy;
  10 +import java.lang.annotation.Target;
  11 +
  12 +/**
  13 + * 车牌号
  14 + */
  15 +@Documented
  16 +@Target({ElementType.FIELD})
  17 +@Retention(RetentionPolicy.RUNTIME)
  18 +@JacksonAnnotationsInside
  19 +@SliderDesensitize(prefixKeep = 3, suffixKeep = 1, replacer = "*") // 车牌号;比如:粤A66666脱敏之后为粤A6***6
  20 +public @interface CarLicenseDesensitize {
  21 +}
yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/annotation/constraints/ChineseNameDesensitize.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.desensitize.annotation.constraints;
  2 +
  3 +import cn.iocoder.yudao.framework.desensitize.annotation.SliderDesensitize;
  4 +import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
  5 +
  6 +import java.lang.annotation.Documented;
  7 +import java.lang.annotation.ElementType;
  8 +import java.lang.annotation.Retention;
  9 +import java.lang.annotation.RetentionPolicy;
  10 +import java.lang.annotation.Target;
  11 +
  12 +/**
  13 + * 中文名
  14 + */
  15 +@Documented
  16 +@Target({ElementType.FIELD})
  17 +@Retention(RetentionPolicy.RUNTIME)
  18 +@JacksonAnnotationsInside
  19 +@SliderDesensitize(prefixKeep = 1, suffixKeep = 0, replacer = "*") // 中文名;比如:刘子豪脱敏之后为刘**
  20 +public @interface ChineseNameDesensitize {
  21 +}
yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/annotation/constraints/EmailDesensitize.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.desensitize.annotation.constraints;
  2 +
  3 +import cn.iocoder.yudao.framework.desensitize.annotation.RegexDesensitize;
  4 +import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
  5 +
  6 +import java.lang.annotation.Documented;
  7 +import java.lang.annotation.ElementType;
  8 +import java.lang.annotation.Retention;
  9 +import java.lang.annotation.RetentionPolicy;
  10 +import java.lang.annotation.Target;
  11 +
  12 +/**
  13 + * 邮箱
  14 + */
  15 +@Documented
  16 +@Target({ElementType.FIELD})
  17 +@Retention(RetentionPolicy.RUNTIME)
  18 +@JacksonAnnotationsInside
  19 +@RegexDesensitize(regex = "(^.)[^@]*(@.*$)", replacer ="$1****$2") // 邮箱;比如:example@gmail.com脱敏之后为e****@gmail.com
  20 +public @interface EmailDesensitize {
  21 +}
yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/annotation/constraints/FixedPhoneDesensitize.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.desensitize.annotation.constraints;
  2 +
  3 +import cn.iocoder.yudao.framework.desensitize.annotation.SliderDesensitize;
  4 +import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
  5 +
  6 +import java.lang.annotation.Documented;
  7 +import java.lang.annotation.ElementType;
  8 +import java.lang.annotation.Retention;
  9 +import java.lang.annotation.RetentionPolicy;
  10 +import java.lang.annotation.Target;
  11 +
  12 +/**
  13 + * 固定电话
  14 + */
  15 +@Documented
  16 +@Target({ElementType.FIELD})
  17 +@Retention(RetentionPolicy.RUNTIME)
  18 +@JacksonAnnotationsInside
  19 +@SliderDesensitize(prefixKeep = 4, suffixKeep = 2, replacer = "*") // 固定电话;比如:01086551122脱敏之后为0108*****22
  20 +public @interface FixedPhoneDesensitize {
  21 +}
yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/annotation/constraints/IdCardDesensitize.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.desensitize.annotation.constraints;
  2 +
  3 +import cn.iocoder.yudao.framework.desensitize.annotation.SliderDesensitize;
  4 +import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
  5 +
  6 +import java.lang.annotation.Documented;
  7 +import java.lang.annotation.ElementType;
  8 +import java.lang.annotation.Retention;
  9 +import java.lang.annotation.RetentionPolicy;
  10 +import java.lang.annotation.Target;
  11 +
  12 +/**
  13 + * 身份证
  14 + */
  15 +@Documented
  16 +@Target({ElementType.FIELD})
  17 +@Retention(RetentionPolicy.RUNTIME)
  18 +@JacksonAnnotationsInside
  19 +@SliderDesensitize(prefixKeep = 6, suffixKeep = 2, replacer = "*") // 身份证号码;比如:530321199204074611脱敏之后为530321**********11
  20 +public @interface IdCardDesensitize {
  21 +}
yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/annotation/constraints/PasswordDesensitize.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.desensitize.annotation.constraints;
  2 +
  3 +import cn.iocoder.yudao.framework.desensitize.annotation.SliderDesensitize;
  4 +import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
  5 +
  6 +import java.lang.annotation.Documented;
  7 +import java.lang.annotation.ElementType;
  8 +import java.lang.annotation.Retention;
  9 +import java.lang.annotation.RetentionPolicy;
  10 +import java.lang.annotation.Target;
  11 +
  12 +/**
  13 + * 密码
  14 + */
  15 +@Documented
  16 +@Target({ElementType.FIELD})
  17 +@Retention(RetentionPolicy.RUNTIME)
  18 +@JacksonAnnotationsInside
  19 +@SliderDesensitize(prefixKeep = 0, suffixKeep = 0, replacer = "*") // 密码;比如:123456脱敏之后为******
  20 +public @interface PasswordDesensitize {
  21 +}
yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/annotation/constraints/PhoneNumberDesensitize.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.desensitize.annotation.constraints;
  2 +
  3 +import cn.iocoder.yudao.framework.desensitize.annotation.SliderDesensitize;
  4 +import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
  5 +
  6 +import java.lang.annotation.Documented;
  7 +import java.lang.annotation.ElementType;
  8 +import java.lang.annotation.Retention;
  9 +import java.lang.annotation.RetentionPolicy;
  10 +import java.lang.annotation.Target;
  11 +
  12 +/**
  13 + * 手机号
  14 + */
  15 +@Documented
  16 +@Target({ElementType.FIELD})
  17 +@Retention(RetentionPolicy.RUNTIME)
  18 +@JacksonAnnotationsInside
  19 +@SliderDesensitize(prefixKeep = 3, suffixKeep = 4, replacer = "*") // 手机号;比如:13248765917脱敏之后为132****5917
  20 +public @interface PhoneNumberDesensitize {
  21 +}
yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/constants/DesensitizeConstants.java deleted
1 -package cn.iocoder.yudao.framework.desensitize.constants;  
2 -  
3 -import lombok.AccessLevel;  
4 -import lombok.NoArgsConstructor;  
5 -  
6 -@NoArgsConstructor(access = AccessLevel.PRIVATE)  
7 -public class DesensitizeConstants {  
8 -  
9 - /**  
10 - * 默认正则  
11 - */  
12 - public static final String DEFAULT_REGEX = null;  
13 -  
14 - /**  
15 - * 默认保持长度  
16 - */  
17 - public static final int DEFAULT_KEEP_LENGTH = -1;  
18 -  
19 - /**  
20 - * 默认替换字符  
21 - */  
22 - public static final String DEFAULT_REPLACER = "****";  
23 -  
24 -}  
yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/enums/DesensitizationStrategyEnum.java deleted
1 -package cn.iocoder.yudao.framework.desensitize.enums;  
2 -  
3 -import lombok.Getter;  
4 -import lombok.RequiredArgsConstructor;  
5 -  
6 -import static cn.iocoder.yudao.framework.desensitize.constants.DesensitizeConstants.DEFAULT_KEEP_LENGTH;  
7 -import static cn.iocoder.yudao.framework.desensitize.constants.DesensitizeConstants.DEFAULT_REGEX;  
8 -import static cn.iocoder.yudao.framework.desensitize.constants.DesensitizeConstants.DEFAULT_REPLACER;  
9 -  
10 -@Getter  
11 -@RequiredArgsConstructor  
12 -public enum DesensitizationStrategyEnum {  
13 - // 常用脱敏业务  
14 - PHONE_NUMBER(DEFAULT_REGEX, 3, 4, DEFAULT_REPLACER), // 手机号;比如:13248765917脱敏之后为132****5917  
15 - FIXED_PHONE(DEFAULT_REGEX, 4, 2, DEFAULT_REPLACER), // 固定电话;比如:01086551122脱敏之后为0108*****22  
16 - ID_CARD(DEFAULT_REGEX, 6, 2, DEFAULT_REPLACER), // 身份证号码;比如:530321199204074611脱敏之后为530321**********11  
17 - BANK_CARD(DEFAULT_REGEX, 6, 2, DEFAULT_REPLACER), // 银行卡号;比如:9988002866797031脱敏之后为998800********31  
18 - CHINESE_NAME(DEFAULT_REGEX, 1, 0, "**"),// 中文名;比如:刘子豪脱敏之后为刘**  
19 - ADDRESS("[\\s\\S]+区", DEFAULT_KEEP_LENGTH, DEFAULT_KEEP_LENGTH, DEFAULT_REPLACER), // 地址只显示到地区,不显示详细地址;比如:广州市天河区幸福小区102号脱敏之后为广州市天河区********  
20 - EMAIL("(^.)[^@]*(@.*$)", DEFAULT_KEEP_LENGTH, DEFAULT_KEEP_LENGTH, "$1****$2"), // 邮箱;比如:example@gmail.com脱敏之后为e******@gmail.com  
21 - CAR_LICENSE(DEFAULT_REGEX, 3, 1, DEFAULT_REPLACER), // 车牌号;比如:粤A66666脱敏之后为粤A6***6  
22 - PASSWORD(DEFAULT_REGEX, 0, 0, DEFAULT_REPLACER), // 密码;比如:123456脱敏之后为******  
23 -  
24 - // 自定义脱敏业务  
25 - REGEX(DEFAULT_REGEX, DEFAULT_KEEP_LENGTH, DEFAULT_KEEP_LENGTH, DEFAULT_REPLACER), // 自定义正则表达式  
26 - SLIDE(DEFAULT_REGEX, DEFAULT_KEEP_LENGTH, DEFAULT_KEEP_LENGTH, DEFAULT_REPLACER), // 滑动脱敏  
27 - CUSTOM_HANDLE(DEFAULT_REGEX, DEFAULT_KEEP_LENGTH, DEFAULT_KEEP_LENGTH, DEFAULT_REPLACER); // 自定义处理器  
28 - ;  
29 -  
30 - /**  
31 - * 正则表达式  
32 - */  
33 - private final String regex;  
34 -  
35 - /**  
36 - * 前缀保留长度  
37 - */  
38 - private final int preKeep;  
39 -  
40 - /**  
41 - * 后缀保留长度  
42 - */  
43 - private final int suffixKeep;  
44 -  
45 - /**  
46 - * 脱敏替换字符  
47 - */  
48 - private final String replacer;  
49 -}  
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 { @@ -8,6 +8,6 @@ public interface DesensitizationHandler {
8 * @param origin 原始字符串 8 * @param origin 原始字符串
9 * @return 脱敏后的字符串 9 * @return 脱敏后的字符串
10 */ 10 */
11 - String handle(String origin); 11 + String desensitize(String origin, Object... arg);
12 12
13 } 13 }
yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/handler/DesensitizationHandlerHolder.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.desensitize.handler;
  2 +
  3 +import cn.hutool.core.util.ReflectUtil;
  4 +
  5 +import java.util.Map;
  6 +import java.util.concurrent.ConcurrentHashMap;
  7 +
  8 +public class DesensitizationHandlerHolder {
  9 + /**
  10 + * handler 缓存,默认初始化内置的处理器
  11 + */
  12 + private static final Map<Class<? extends DesensitizationHandler>, DesensitizationHandler> HANDLER_MAP = new ConcurrentHashMap<>() {{
  13 + put(RegexDesensitizationHandler.class, new RegexDesensitizationHandler());
  14 + put(SliderDesensitizationHandler.class, new SliderDesensitizationHandler());
  15 + }};
  16 +
  17 + public static DesensitizationHandler getDesensitizationHandler(Class<? extends DesensitizationHandler> clazz) {
  18 + DesensitizationHandler handler = HANDLER_MAP.get(clazz);
  19 + if (handler != null) {
  20 + return handler;
  21 + }
  22 + synchronized (DesensitizationHandlerHolder.class) {
  23 + handler = HANDLER_MAP.get(clazz);
  24 + // 双重校验锁
  25 + if (handler != null) {
  26 + return handler;
  27 + }
  28 + handler = ReflectUtil.newInstanceIfPossible(clazz);
  29 + HANDLER_MAP.put(clazz, handler);
  30 + }
  31 + return handler;
  32 + }
  33 +
  34 +}
yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/handler/DefaultDesensitizationHandler.java renamed to yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/handler/RegexDesensitizationHandler.java
1 package cn.iocoder.yudao.framework.desensitize.handler; 1 package cn.iocoder.yudao.framework.desensitize.handler;
2 2
3 -public class DefaultDesensitizationHandler implements DesensitizationHandler { 3 +public class RegexDesensitizationHandler implements DesensitizationHandler {
4 4
5 @Override 5 @Override
6 - public String handle(String origin) {  
7 - return origin; 6 + public String desensitize(String origin, Object... arg) {
  7 + String regex = (String) arg[0];
  8 + String replacer = (String) arg[1];
  9 +
  10 + return origin.replaceAll(regex, replacer);
8 } 11 }
9 12
10 } 13 }
yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/handler/SliderDesensitizationHandler.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.desensitize.handler;
  2 +
  3 +public class SliderDesensitizationHandler implements DesensitizationHandler {
  4 +
  5 + @Override
  6 + public String desensitize(String origin, Object... arg) {
  7 + int prefixKeep = (Integer) arg[0];
  8 + int suffixKeep = (Integer) arg[1];
  9 + String replacer = (String) arg[2];
  10 +
  11 + int length = origin.length();
  12 +
  13 + // 原始字符串长度小于等于保留长度,则原始字符串全部替换
  14 + if (prefixKeep >= length || suffixKeep >= length) {
  15 + return buildReplacerByLength(replacer, length);
  16 + }
  17 +
  18 + // 如果原始字符串小于等于前后缀保留字符串长度,则原始字符串全部替换
  19 + if ((prefixKeep + suffixKeep) >= length) {
  20 + return buildReplacerByLength(replacer, length);
  21 + }
  22 +
  23 + int interval = length - prefixKeep - suffixKeep;
  24 + return origin.substring(0, prefixKeep) +
  25 + buildReplacerByLength(replacer, interval) +
  26 + origin.substring(prefixKeep + interval);
  27 + }
  28 +
  29 + /**
  30 + * 根据长度循环构建替换符
  31 + *
  32 + * @param replacer 替换符
  33 + * @param length 长度
  34 + * @return 构建后的替换符
  35 + */
  36 + private String buildReplacerByLength(String replacer, int length) {
  37 + return String.valueOf(replacer).repeat(Math.max(0, length));
  38 + }
  39 +}
yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/serializer/StringDesensitizeSerializer.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.desensitize.serializer;
  2 +
  3 +import cn.hutool.core.util.ReflectUtil;
  4 +import cn.hutool.core.util.StrUtil;
  5 +import cn.iocoder.yudao.framework.desensitize.annotation.Desensitize;
  6 +import cn.iocoder.yudao.framework.desensitize.annotation.RegexDesensitize;
  7 +import cn.iocoder.yudao.framework.desensitize.annotation.SliderDesensitize;
  8 +import cn.iocoder.yudao.framework.desensitize.handler.DesensitizationHandler;
  9 +import cn.iocoder.yudao.framework.desensitize.handler.DesensitizationHandlerHolder;
  10 +import com.fasterxml.jackson.core.JsonGenerator;
  11 +import com.fasterxml.jackson.databind.BeanProperty;
  12 +import com.fasterxml.jackson.databind.JsonMappingException;
  13 +import com.fasterxml.jackson.databind.JsonSerializer;
  14 +import com.fasterxml.jackson.databind.SerializerProvider;
  15 +import com.fasterxml.jackson.databind.ser.ContextualSerializer;
  16 +import com.fasterxml.jackson.databind.ser.std.StdSerializer;
  17 +
  18 +import java.io.IOException;
  19 +import java.lang.reflect.Field;
  20 +
  21 +/**
  22 + * 脱敏序列化器
  23 + */
  24 +public class StringDesensitizeSerializer extends StdSerializer<String> implements ContextualSerializer {
  25 + private final DesensitizationHandler desensitizationHandler;
  26 +
  27 + protected StringDesensitizeSerializer(DesensitizationHandler desensitizationHandler) {
  28 + super(String.class);
  29 + this.desensitizationHandler = desensitizationHandler;
  30 + }
  31 +
  32 +
  33 + @Override
  34 + public JsonSerializer<?> createContextual(SerializerProvider serializerProvider, BeanProperty beanProperty) throws JsonMappingException {
  35 + Desensitize annotation = beanProperty.getAnnotation(Desensitize.class);
  36 + if (annotation == null) {
  37 + return this;
  38 + }
  39 +
  40 + return new StringDesensitizeSerializer(DesensitizationHandlerHolder.getDesensitizationHandler(annotation.desensitizationHandler()));
  41 + }
  42 +
  43 + @Override
  44 + public void serialize(String value, JsonGenerator gen, SerializerProvider serializerProvider) throws IOException {
  45 + if (StrUtil.isBlank(value)) {
  46 + gen.writeNull();
  47 + return;
  48 + }
  49 +
  50 + String currentName = gen.getOutputContext().getCurrentName();
  51 + Object currentValue = gen.getCurrentValue();
  52 + Class<?> currentValueClass = currentValue.getClass();
  53 + Field field = ReflectUtil.getField(currentValueClass, currentName);
  54 +
  55 + // 滑动处理器
  56 + SliderDesensitize sliderDesensitize = field.getAnnotation(SliderDesensitize.class);
  57 + if (sliderDesensitize != null) {
  58 + value = this.desensitizationHandler.desensitize(value, sliderDesensitize.prefixKeep(), sliderDesensitize.suffixKeep(), sliderDesensitize.replacer());
  59 + }
  60 +
  61 + // 正则处理器
  62 + RegexDesensitize regexDesensitize = field.getAnnotation(RegexDesensitize.class);
  63 + if (regexDesensitize != null) {
  64 + value = this.desensitizationHandler.desensitize(value, regexDesensitize.regex(), regexDesensitize.replacer());
  65 + }
  66 +
  67 + // 自定义处理器
  68 + Desensitize desensitize = field.getAnnotation(Desensitize.class);
  69 + if (desensitize != null) {
  70 + value = this.desensitizationHandler.desensitize(value);
  71 + }
  72 +
  73 + gen.writeString(value);
  74 + }
  75 +
  76 +}
yudao-framework/yudao-spring-boot-starter-biz-desensitize/src/test/java/cn/iocoder/yudao/framework/desensitize/handler/DesensitizationHandlerTest.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.desensitize.handler;
  2 +
  3 +import org.junit.jupiter.api.Assertions;
  4 +import org.junit.jupiter.api.Test;
  5 +
  6 +public class DesensitizationHandlerTest {
  7 +
  8 + @Test
  9 + public void testSliderDesensitizationHandler() {
  10 + DesensitizationHandler handler = DesensitizationHandlerHolder.getDesensitizationHandler(SliderDesensitizationHandler.class);
  11 +
  12 + Assertions.assertEquals("A****FG", handler.desensitize("ABCDEFG", 1, 2, "*"));
  13 + Assertions.assertEquals("芋**码", handler.desensitize("芋道源码", 1, 1, "*"));
  14 + Assertions.assertEquals("****", handler.desensitize("芋道源码", 4, 0, "*"));
  15 + }
  16 +
  17 + @Test
  18 + public void testRegexDesensitizationHandler() {
  19 + DesensitizationHandler handler = DesensitizationHandlerHolder.getDesensitizationHandler(RegexDesensitizationHandler.class);
  20 +
  21 + Assertions.assertEquals("e****@gmail.com", handler.desensitize("example@gmail.com", "(^.)[^@]*(@.*$)", "$1****$2"));
  22 + Assertions.assertEquals("***,铁***", handler.desensitize("他妈的,铁废物", "他妈的|去你大爷|卧槽|草泥马|废物", "***"));
  23 + }
  24 +
  25 +}