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 4 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5 5 <modelVersion>4.0.0</modelVersion>
6 6 <parent>
7   - <groupId>cn.iocoder.boot</groupId>
8 7 <artifactId>yudao-framework</artifactId>
9   - <version>1.6.6-snapshot</version>
  8 + <groupId>cn.iocoder.boot</groupId>
  9 + <version>${revision}</version>
10 10 </parent>
11 11  
12 12 <artifactId>yudao-spring-boot-starter-biz-desensitize</artifactId>
... ... @@ -22,5 +22,22 @@
22 22 <groupId>cn.iocoder.boot</groupId>
23 23 <artifactId>yudao-common</artifactId>
24 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 42 </dependencies>
26 43 </project>
27 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 1 package cn.iocoder.yudao.framework.desensitize.annotation;
2 2  
3   -import cn.iocoder.yudao.framework.desensitize.enums.DesensitizationStrategyEnum;
4 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 8 import java.lang.annotation.Documented;
7 9 import java.lang.annotation.ElementType;
... ... @@ -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 18 @Documented
  19 +@Target({ElementType.FIELD, ElementType.ANNOTATION_TYPE})
  20 +@Retention(RetentionPolicy.RUNTIME)
  21 +@JacksonAnnotationsInside
  22 +@JsonSerialize(using = StringDesensitizeSerializer.class)
19 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 8 * @param origin 原始字符串
9 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 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 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 +}
... ...