mirror of
https://gitee.com/huangge1199_admin/vue-pro.git
synced 2024-11-30 11:11:55 +08:00
feat: 支持 vo 返回的脱敏
This commit is contained in:
parent
e637bff8cd
commit
5c8e41b847
@ -4,9 +4,9 @@
|
|||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>cn.iocoder.boot</groupId>
|
|
||||||
<artifactId>yudao-framework</artifactId>
|
<artifactId>yudao-framework</artifactId>
|
||||||
<version>1.6.6-snapshot</version>
|
<groupId>cn.iocoder.boot</groupId>
|
||||||
|
<version>${revision}</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>yudao-spring-boot-starter-biz-desensitize</artifactId>
|
<artifactId>yudao-spring-boot-starter-biz-desensitize</artifactId>
|
||||||
@ -22,5 +22,22 @@
|
|||||||
<groupId>cn.iocoder.boot</groupId>
|
<groupId>cn.iocoder.boot</groupId>
|
||||||
<artifactId>yudao-common</artifactId>
|
<artifactId>yudao-common</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- jackson -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.fasterxml.jackson.core</groupId>
|
||||||
|
<artifactId>jackson-annotations</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.fasterxml.jackson.core</groupId>
|
||||||
|
<artifactId>jackson-databind</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Test 测试相关 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.iocoder.boot</groupId>
|
||||||
|
<artifactId>yudao-spring-boot-starter-test</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</project>
|
</project>
|
@ -1,7 +1,9 @@
|
|||||||
package cn.iocoder.yudao.framework.desensitize.annotation;
|
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.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.Documented;
|
||||||
import java.lang.annotation.ElementType;
|
import java.lang.annotation.ElementType;
|
||||||
@ -11,40 +13,18 @@ import java.lang.annotation.Target;
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Desensitize 注解配置会覆盖 DesensitizationStrategyEnum 配置
|
* Desensitize 顶级脱敏注解
|
||||||
*/
|
*/
|
||||||
@Target({ElementType.FIELD})
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
@Documented
|
@Documented
|
||||||
|
@Target({ElementType.FIELD, ElementType.ANNOTATION_TYPE})
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@JacksonAnnotationsInside
|
||||||
|
@JsonSerialize(using = StringDesensitizeSerializer.class)
|
||||||
public @interface Desensitize {
|
public @interface Desensitize {
|
||||||
|
|
||||||
/**
|
|
||||||
* 脱敏策略
|
|
||||||
*/
|
|
||||||
DesensitizationStrategyEnum strategy();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 脱敏替换字符
|
|
||||||
*/
|
|
||||||
String replacer();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 正则表达式
|
|
||||||
*/
|
|
||||||
String regex();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 前缀保留长度
|
|
||||||
*/
|
|
||||||
int preKeep();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 后缀保留长度
|
|
||||||
*/
|
|
||||||
int suffixKeep();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 脱敏处理器
|
* 脱敏处理器
|
||||||
*/
|
*/
|
||||||
Class<? extends DesensitizationHandler> handler();
|
Class<? extends DesensitizationHandler> desensitizationHandler();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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 "******";
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
@ -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 {
|
||||||
|
}
|
@ -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 {
|
||||||
|
}
|
@ -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 {
|
||||||
|
}
|
@ -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 {
|
||||||
|
}
|
@ -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 {
|
||||||
|
}
|
@ -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 {
|
||||||
|
}
|
@ -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 {
|
||||||
|
}
|
@ -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 {
|
||||||
|
}
|
@ -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 = "****";
|
|
||||||
|
|
||||||
}
|
|
@ -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;
|
|
||||||
}
|
|
@ -1,10 +0,0 @@
|
|||||||
package cn.iocoder.yudao.framework.desensitize.handler;
|
|
||||||
|
|
||||||
public class DefaultDesensitizationHandler implements DesensitizationHandler {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String handle(String origin) {
|
|
||||||
return origin;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -8,6 +8,6 @@ public interface DesensitizationHandler {
|
|||||||
* @param origin 原始字符串
|
* @param origin 原始字符串
|
||||||
* @return 脱敏后的字符串
|
* @return 脱敏后的字符串
|
||||||
*/
|
*/
|
||||||
String handle(String origin);
|
String desensitize(String origin, Object... arg);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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<Class<? extends DesensitizationHandler>, DesensitizationHandler> HANDLER_MAP = new ConcurrentHashMap<>() {{
|
||||||
|
put(RegexDesensitizationHandler.class, new RegexDesensitizationHandler());
|
||||||
|
put(SliderDesensitizationHandler.class, new SliderDesensitizationHandler());
|
||||||
|
}};
|
||||||
|
|
||||||
|
public static DesensitizationHandler getDesensitizationHandler(Class<? extends DesensitizationHandler> 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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));
|
||||||
|
}
|
||||||
|
}
|
@ -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<String> 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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("他妈的,铁废物", "他妈的|去你大爷|卧槽|草泥马|废物", "***"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user