mirror of
				https://gitee.com/hhyykk/ipms-sjy.git
				synced 2025-10-30 09:48:43 +08:00 
			
		
		
		
	| @@ -143,6 +143,11 @@ | |||||||
|                 <artifactId>yudao-spring-boot-starter-captcha</artifactId> |                 <artifactId>yudao-spring-boot-starter-captcha</artifactId> | ||||||
|                 <version>${revision}</version> |                 <version>${revision}</version> | ||||||
|             </dependency> |             </dependency> | ||||||
|  |             <dependency> | ||||||
|  |                 <groupId>cn.iocoder.boot</groupId> | ||||||
|  |                 <artifactId>yudao-spring-boot-starter-desensitize</artifactId> | ||||||
|  |                 <version>${revision}</version> | ||||||
|  |             </dependency> | ||||||
|  |  | ||||||
|             <!-- Spring 核心 --> |             <!-- Spring 核心 --> | ||||||
|             <dependency> |             <dependency> | ||||||
|   | |||||||
| @@ -41,6 +41,7 @@ | |||||||
|         <module>yudao-spring-boot-starter-flowable</module> |         <module>yudao-spring-boot-starter-flowable</module> | ||||||
|         <module>yudao-spring-boot-starter-captcha</module> |         <module>yudao-spring-boot-starter-captcha</module> | ||||||
|         <module>yudao-spring-boot-starter-websocket</module> |         <module>yudao-spring-boot-starter-websocket</module> | ||||||
|  |         <module>yudao-spring-boot-starter-desensitize</module> | ||||||
|     </modules> |     </modules> | ||||||
|  |  | ||||||
|     <artifactId>yudao-framework</artifactId> |     <artifactId>yudao-framework</artifactId> | ||||||
|   | |||||||
| @@ -0,0 +1,38 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <project xmlns="http://maven.apache.org/POM/4.0.0" | ||||||
|  |          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||||||
|  |          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> | ||||||
|  |     <parent> | ||||||
|  |         <artifactId>yudao-framework</artifactId> | ||||||
|  |         <groupId>cn.iocoder.boot</groupId> | ||||||
|  |         <version>${revision}</version> | ||||||
|  |     </parent> | ||||||
|  |  | ||||||
|  |     <artifactId>yudao-spring-boot-starter-desensitize</artifactId> | ||||||
|  |     <description>脱敏组件:支持 JSON 返回数据时,将邮箱、手机等字段进行脱敏</description> | ||||||
|  |  | ||||||
|  |     <dependencies> | ||||||
|  |         <dependency> | ||||||
|  |             <groupId>cn.iocoder.boot</groupId> | ||||||
|  |             <artifactId>yudao-common</artifactId> | ||||||
|  |         </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> | ||||||
|  | </project> | ||||||
| @@ -0,0 +1,32 @@ | |||||||
|  | package cn.iocoder.yudao.framework.desensitize.core.base.annotation; | ||||||
|  |  | ||||||
|  | import cn.iocoder.yudao.framework.desensitize.core.base.handler.DesensitizationHandler; | ||||||
|  | import cn.iocoder.yudao.framework.desensitize.core.base.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; | ||||||
|  | import java.lang.annotation.Retention; | ||||||
|  | import java.lang.annotation.RetentionPolicy; | ||||||
|  | import java.lang.annotation.Target; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 顶级脱敏注解,自定义注解需要使用此注解 | ||||||
|  |  * | ||||||
|  |  * @author gaibu | ||||||
|  |  */ | ||||||
|  | @Documented | ||||||
|  | @Target(ElementType.ANNOTATION_TYPE) | ||||||
|  | @Retention(RetentionPolicy.RUNTIME) | ||||||
|  | @JacksonAnnotationsInside // 此注解是其他所有 jackson 注解的元注解,打上了此注解的注解表明是 jackson 注解的一部分 | ||||||
|  | @JsonSerialize(using = StringDesensitizeSerializer.class) // 指定序列化器 | ||||||
|  | public @interface DesensitizeBy { | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 脱敏处理器 | ||||||
|  |      */ | ||||||
|  |     @SuppressWarnings("rawtypes") | ||||||
|  |     Class<? extends DesensitizationHandler> handler(); | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -0,0 +1,21 @@ | |||||||
|  | package cn.iocoder.yudao.framework.desensitize.core.base.handler; | ||||||
|  |  | ||||||
|  | import java.lang.annotation.Annotation; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 脱敏处理器接口 | ||||||
|  |  * | ||||||
|  |  * @author gaibu | ||||||
|  |  */ | ||||||
|  | public interface DesensitizationHandler<T extends Annotation> { | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 脱敏 | ||||||
|  |      * | ||||||
|  |      * @param origin     原始字符串 | ||||||
|  |      * @param annotation 注解信息 | ||||||
|  |      * @return 脱敏后的字符串 | ||||||
|  |      */ | ||||||
|  |     String desensitize(String origin, T annotation); | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -0,0 +1,92 @@ | |||||||
|  | package cn.iocoder.yudao.framework.desensitize.core.base.serializer; | ||||||
|  |  | ||||||
|  | import cn.hutool.core.annotation.AnnotationUtil; | ||||||
|  | import cn.hutool.core.lang.Singleton; | ||||||
|  | import cn.hutool.core.util.ArrayUtil; | ||||||
|  | import cn.hutool.core.util.ReflectUtil; | ||||||
|  | import cn.hutool.core.util.StrUtil; | ||||||
|  | import cn.iocoder.yudao.framework.desensitize.core.base.annotation.DesensitizeBy; | ||||||
|  | import cn.iocoder.yudao.framework.desensitize.core.base.handler.DesensitizationHandler; | ||||||
|  | import com.fasterxml.jackson.core.JsonGenerator; | ||||||
|  | import com.fasterxml.jackson.databind.BeanProperty; | ||||||
|  | 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 lombok.Getter; | ||||||
|  | import lombok.Setter; | ||||||
|  |  | ||||||
|  | import java.io.IOException; | ||||||
|  | import java.lang.annotation.Annotation; | ||||||
|  | import java.lang.reflect.Field; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 脱敏序列化器 | ||||||
|  |  * | ||||||
|  |  * 实现 JSON 返回数据时,使用 {@link DesensitizationHandler} 对声明脱敏注解的字段,进行脱敏处理。 | ||||||
|  |  * | ||||||
|  |  * @author gaibu | ||||||
|  |  */ | ||||||
|  | @SuppressWarnings("rawtypes") | ||||||
|  | public class StringDesensitizeSerializer extends StdSerializer<String> implements ContextualSerializer { | ||||||
|  |  | ||||||
|  |     @Getter | ||||||
|  |     @Setter | ||||||
|  |     private DesensitizationHandler desensitizationHandler; | ||||||
|  |  | ||||||
|  |     protected StringDesensitizeSerializer() { | ||||||
|  |         super(String.class); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public JsonSerializer<?> createContextual(SerializerProvider serializerProvider, BeanProperty beanProperty) { | ||||||
|  |         DesensitizeBy annotation = beanProperty.getAnnotation(DesensitizeBy.class); | ||||||
|  |         if (annotation == null) { | ||||||
|  |             return this; | ||||||
|  |         } | ||||||
|  |         // 创建一个 StringDesensitizeSerializer 对象,使用 DesensitizeBy 对应的处理器 | ||||||
|  |         StringDesensitizeSerializer serializer = new StringDesensitizeSerializer(); | ||||||
|  |         serializer.setDesensitizationHandler(Singleton.get(annotation.handler())); | ||||||
|  |         return serializer; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     @SuppressWarnings("unchecked") | ||||||
|  |     public void serialize(String value, JsonGenerator gen, SerializerProvider serializerProvider) throws IOException { | ||||||
|  |         if (StrUtil.isBlank(value)) { | ||||||
|  |             gen.writeNull(); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |         // 获取序列化字段 | ||||||
|  |         Field field = getField(gen); | ||||||
|  |  | ||||||
|  |         // 自定义处理器 | ||||||
|  |         DesensitizeBy[] annotations = AnnotationUtil.getCombinationAnnotations(field, DesensitizeBy.class); | ||||||
|  |         if (ArrayUtil.isEmpty(annotations)) { | ||||||
|  |             gen.writeString(value); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |         for (Annotation annotation : field.getAnnotations()) { | ||||||
|  |             if (AnnotationUtil.hasAnnotation(annotation.annotationType(), DesensitizeBy.class)) { | ||||||
|  |                 value = this.desensitizationHandler.desensitize(value, annotation); | ||||||
|  |                 gen.writeString(value); | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         gen.writeString(value); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 获取字段 | ||||||
|  |      * | ||||||
|  |      * @param generator JsonGenerator | ||||||
|  |      * @return 字段 | ||||||
|  |      */ | ||||||
|  |     private Field getField(JsonGenerator generator) { | ||||||
|  |         String currentName = generator.getOutputContext().getCurrentName(); | ||||||
|  |         Object currentValue = generator.getCurrentValue(); | ||||||
|  |         Class<?> currentValueClass = currentValue.getClass(); | ||||||
|  |         return ReflectUtil.getField(currentValueClass, currentName); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -0,0 +1,4 @@ | |||||||
|  | /** | ||||||
|  |  * 脱敏组件:支持 JSON 返回数据时,将邮箱、手机等字段进行脱敏 | ||||||
|  |  */ | ||||||
|  | package cn.iocoder.yudao.framework.desensitize.core; | ||||||
| @@ -0,0 +1,36 @@ | |||||||
|  | package cn.iocoder.yudao.framework.desensitize.core.regex.annotation; | ||||||
|  |  | ||||||
|  | import cn.iocoder.yudao.framework.desensitize.core.base.annotation.DesensitizeBy; | ||||||
|  | import cn.iocoder.yudao.framework.desensitize.core.regex.handler.EmailDesensitizationHandler; | ||||||
|  | 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; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 邮箱脱敏注解 | ||||||
|  |  * | ||||||
|  |  * @author gaibu | ||||||
|  |  */ | ||||||
|  | @Documented | ||||||
|  | @Target({ElementType.FIELD}) | ||||||
|  | @Retention(RetentionPolicy.RUNTIME) | ||||||
|  | @JacksonAnnotationsInside | ||||||
|  | @DesensitizeBy(handler = EmailDesensitizationHandler.class) | ||||||
|  | public @interface EmailDesensitize { | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 匹配的正则表达式 | ||||||
|  |      */ | ||||||
|  |     String regex() default "(^.)[^@]*(@.*$)"; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 替换规则,邮箱; | ||||||
|  |      * | ||||||
|  |      * 比如:example@gmail.com 脱敏之后 为e****@gmail.com | ||||||
|  |      */ | ||||||
|  |     String replacer() default "$1****$2"; | ||||||
|  | } | ||||||
| @@ -0,0 +1,38 @@ | |||||||
|  | package cn.iocoder.yudao.framework.desensitize.core.regex.annotation; | ||||||
|  |  | ||||||
|  | import cn.iocoder.yudao.framework.desensitize.core.base.annotation.DesensitizeBy; | ||||||
|  | import cn.iocoder.yudao.framework.desensitize.core.regex.handler.DefaultRegexDesensitizationHandler; | ||||||
|  | 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; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 正则脱敏注解 | ||||||
|  |  * | ||||||
|  |  * @author gaibu | ||||||
|  |  */ | ||||||
|  | @Documented | ||||||
|  | @Target({ElementType.FIELD, ElementType.ANNOTATION_TYPE}) | ||||||
|  | @Retention(RetentionPolicy.RUNTIME) | ||||||
|  | @JacksonAnnotationsInside | ||||||
|  | @DesensitizeBy(handler = DefaultRegexDesensitizationHandler.class) | ||||||
|  | public @interface RegexDesensitize { | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 匹配的正则表达式(默认匹配所有) | ||||||
|  |      */ | ||||||
|  |     String regex() default "^[\\s\\S]*$"; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 替换规则,会将匹配到的字符串全部替换成 replacer | ||||||
|  |      * | ||||||
|  |      * 例如:regex=123; replacer=****** | ||||||
|  |      * 原始字符串 123456789 | ||||||
|  |      * 脱敏后字符串 ******456789 | ||||||
|  |      */ | ||||||
|  |     String replacer() default "******"; | ||||||
|  | } | ||||||
| @@ -0,0 +1,38 @@ | |||||||
|  | package cn.iocoder.yudao.framework.desensitize.core.regex.handler; | ||||||
|  |  | ||||||
|  | import cn.iocoder.yudao.framework.desensitize.core.base.handler.DesensitizationHandler; | ||||||
|  |  | ||||||
|  | import java.lang.annotation.Annotation; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 正则表达式脱敏处理器抽象类,已实现通用的方法 | ||||||
|  |  * | ||||||
|  |  * @author gaibu | ||||||
|  |  */ | ||||||
|  | public abstract class AbstractRegexDesensitizationHandler<T extends Annotation> | ||||||
|  |         implements DesensitizationHandler<T> { | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public String desensitize(String origin, T annotation) { | ||||||
|  |         String regex = getRegex(annotation); | ||||||
|  |         String replacer = getReplacer(annotation); | ||||||
|  |         return origin.replaceAll(regex, replacer); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 获取注解上的 regex 参数 | ||||||
|  |      * | ||||||
|  |      * @param annotation 注解信息 | ||||||
|  |      * @return 正则表达式 | ||||||
|  |      */ | ||||||
|  |     abstract String getRegex(T annotation); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 获取注解上的 replacer 参数 | ||||||
|  |      * | ||||||
|  |      * @param annotation 注解信息 | ||||||
|  |      * @return 待替换的字符串 | ||||||
|  |      */ | ||||||
|  |     abstract String getReplacer(T annotation); | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -0,0 +1,21 @@ | |||||||
|  | package cn.iocoder.yudao.framework.desensitize.core.regex.handler; | ||||||
|  |  | ||||||
|  | import cn.iocoder.yudao.framework.desensitize.core.regex.annotation.RegexDesensitize; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * {@link RegexDesensitize} 的正则脱敏处理器 | ||||||
|  |  * | ||||||
|  |  * @author gaibu | ||||||
|  |  */ | ||||||
|  | public class DefaultRegexDesensitizationHandler extends AbstractRegexDesensitizationHandler<RegexDesensitize> { | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     String getRegex(RegexDesensitize annotation) { | ||||||
|  |         return annotation.regex(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     String getReplacer(RegexDesensitize annotation) { | ||||||
|  |         return annotation.replacer(); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -0,0 +1,22 @@ | |||||||
|  | package cn.iocoder.yudao.framework.desensitize.core.regex.handler; | ||||||
|  |  | ||||||
|  | import cn.iocoder.yudao.framework.desensitize.core.regex.annotation.EmailDesensitize; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * {@link EmailDesensitize} 的脱敏处理器 | ||||||
|  |  * | ||||||
|  |  * @author gaibu | ||||||
|  |  */ | ||||||
|  | public class EmailDesensitizationHandler extends AbstractRegexDesensitizationHandler<EmailDesensitize> { | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     String getRegex(EmailDesensitize annotation) { | ||||||
|  |         return annotation.regex(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     String getReplacer(EmailDesensitize annotation) { | ||||||
|  |         return annotation.replacer(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -0,0 +1,40 @@ | |||||||
|  | package cn.iocoder.yudao.framework.desensitize.core.slider.annotation; | ||||||
|  |  | ||||||
|  | import cn.iocoder.yudao.framework.desensitize.core.base.annotation.DesensitizeBy; | ||||||
|  | import cn.iocoder.yudao.framework.desensitize.core.slider.handler.BankCardDesensitization; | ||||||
|  | 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; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 银行卡号 | ||||||
|  |  * | ||||||
|  |  * @author gaibu | ||||||
|  |  */ | ||||||
|  | @Documented | ||||||
|  | @Target({ElementType.FIELD}) | ||||||
|  | @Retention(RetentionPolicy.RUNTIME) | ||||||
|  | @JacksonAnnotationsInside | ||||||
|  | @DesensitizeBy(handler = BankCardDesensitization.class) | ||||||
|  | public @interface BankCardDesensitize { | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 前缀保留长度 | ||||||
|  |      */ | ||||||
|  |     int prefixKeep() default 6; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 后缀保留长度 | ||||||
|  |      */ | ||||||
|  |     int suffixKeep() default 2; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 替换规则,银行卡号;比如:9988002866797031脱敏之后为998800********31 | ||||||
|  |      */ | ||||||
|  |     String replacer() default "*"; | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -0,0 +1,40 @@ | |||||||
|  | package cn.iocoder.yudao.framework.desensitize.core.slider.annotation; | ||||||
|  |  | ||||||
|  | import cn.iocoder.yudao.framework.desensitize.core.base.annotation.DesensitizeBy; | ||||||
|  | import cn.iocoder.yudao.framework.desensitize.core.slider.handler.CarLicenseDesensitization; | ||||||
|  | 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; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 车牌号 | ||||||
|  |  * | ||||||
|  |  * @author gaibu | ||||||
|  |  */ | ||||||
|  | @Documented | ||||||
|  | @Target({ElementType.FIELD}) | ||||||
|  | @Retention(RetentionPolicy.RUNTIME) | ||||||
|  | @JacksonAnnotationsInside | ||||||
|  | @DesensitizeBy(handler = CarLicenseDesensitization.class) | ||||||
|  | public @interface CarLicenseDesensitize { | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 前缀保留长度 | ||||||
|  |      */ | ||||||
|  |     int prefixKeep() default 3; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 后缀保留长度 | ||||||
|  |      */ | ||||||
|  |     int suffixKeep() default 1; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 替换规则,车牌号;比如:粤A66666脱敏之后为粤A6***6 | ||||||
|  |      */ | ||||||
|  |     String replacer() default "*"; | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -0,0 +1,40 @@ | |||||||
|  | package cn.iocoder.yudao.framework.desensitize.core.slider.annotation; | ||||||
|  |  | ||||||
|  | import cn.iocoder.yudao.framework.desensitize.core.base.annotation.DesensitizeBy; | ||||||
|  | import cn.iocoder.yudao.framework.desensitize.core.slider.handler.ChineseNameDesensitization; | ||||||
|  | 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; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 中文名 | ||||||
|  |  * | ||||||
|  |  * @author gaibu | ||||||
|  |  */ | ||||||
|  | @Documented | ||||||
|  | @Target({ElementType.FIELD}) | ||||||
|  | @Retention(RetentionPolicy.RUNTIME) | ||||||
|  | @JacksonAnnotationsInside | ||||||
|  | @DesensitizeBy(handler = ChineseNameDesensitization.class) | ||||||
|  | public @interface ChineseNameDesensitize { | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 前缀保留长度 | ||||||
|  |      */ | ||||||
|  |     int prefixKeep() default 1; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 后缀保留长度 | ||||||
|  |      */ | ||||||
|  |     int suffixKeep() default 0; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 替换规则,中文名;比如:刘子豪脱敏之后为刘** | ||||||
|  |      */ | ||||||
|  |     String replacer() default "*"; | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -0,0 +1,40 @@ | |||||||
|  | package cn.iocoder.yudao.framework.desensitize.core.slider.annotation; | ||||||
|  |  | ||||||
|  | import cn.iocoder.yudao.framework.desensitize.core.base.annotation.DesensitizeBy; | ||||||
|  | import cn.iocoder.yudao.framework.desensitize.core.slider.handler.FixedPhoneDesensitization; | ||||||
|  | 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; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 固定电话 | ||||||
|  |  * | ||||||
|  |  * @author gaibu | ||||||
|  |  */ | ||||||
|  | @Documented | ||||||
|  | @Target({ElementType.FIELD}) | ||||||
|  | @Retention(RetentionPolicy.RUNTIME) | ||||||
|  | @JacksonAnnotationsInside | ||||||
|  | @DesensitizeBy(handler = FixedPhoneDesensitization.class) | ||||||
|  | public @interface FixedPhoneDesensitize { | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 前缀保留长度 | ||||||
|  |      */ | ||||||
|  |     int prefixKeep() default 4; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 后缀保留长度 | ||||||
|  |      */ | ||||||
|  |     int suffixKeep() default 2; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 替换规则,固定电话;比如:01086551122脱敏之后为0108*****22 | ||||||
|  |      */ | ||||||
|  |     String replacer() default "*"; | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -0,0 +1,40 @@ | |||||||
|  | package cn.iocoder.yudao.framework.desensitize.core.slider.annotation; | ||||||
|  |  | ||||||
|  | import cn.iocoder.yudao.framework.desensitize.core.base.annotation.DesensitizeBy; | ||||||
|  | import cn.iocoder.yudao.framework.desensitize.core.slider.handler.IdCardDesensitization; | ||||||
|  | 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; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 身份证 | ||||||
|  |  * | ||||||
|  |  * @author gaibu | ||||||
|  |  */ | ||||||
|  | @Documented | ||||||
|  | @Target({ElementType.FIELD}) | ||||||
|  | @Retention(RetentionPolicy.RUNTIME) | ||||||
|  | @JacksonAnnotationsInside | ||||||
|  | @DesensitizeBy(handler = IdCardDesensitization.class) | ||||||
|  | public @interface IdCardDesensitize { | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 前缀保留长度 | ||||||
|  |      */ | ||||||
|  |     int prefixKeep() default 6; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 后缀保留长度 | ||||||
|  |      */ | ||||||
|  |     int suffixKeep() default 2; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 替换规则,身份证号码;比如:530321199204074611脱敏之后为530321**********11 | ||||||
|  |      */ | ||||||
|  |     String replacer() default "*"; | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -0,0 +1,40 @@ | |||||||
|  | package cn.iocoder.yudao.framework.desensitize.core.slider.annotation; | ||||||
|  |  | ||||||
|  | import cn.iocoder.yudao.framework.desensitize.core.base.annotation.DesensitizeBy; | ||||||
|  | import cn.iocoder.yudao.framework.desensitize.core.slider.handler.MobileDesensitization; | ||||||
|  | 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; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 手机号 | ||||||
|  |  * | ||||||
|  |  * @author gaibu | ||||||
|  |  */ | ||||||
|  | @Documented | ||||||
|  | @Target({ElementType.FIELD}) | ||||||
|  | @Retention(RetentionPolicy.RUNTIME) | ||||||
|  | @JacksonAnnotationsInside | ||||||
|  | @DesensitizeBy(handler = MobileDesensitization.class) | ||||||
|  | public @interface MobileDesensitize { | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 前缀保留长度 | ||||||
|  |      */ | ||||||
|  |     int prefixKeep() default 3; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 后缀保留长度 | ||||||
|  |      */ | ||||||
|  |     int suffixKeep() default 4; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 替换规则,手机号;比如:13248765917脱敏之后为132****5917 | ||||||
|  |      */ | ||||||
|  |     String replacer() default "*"; | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -0,0 +1,42 @@ | |||||||
|  | package cn.iocoder.yudao.framework.desensitize.core.slider.annotation; | ||||||
|  |  | ||||||
|  | import cn.iocoder.yudao.framework.desensitize.core.base.annotation.DesensitizeBy; | ||||||
|  | import cn.iocoder.yudao.framework.desensitize.core.slider.handler.PasswordDesensitization; | ||||||
|  | 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; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 密码 | ||||||
|  |  * | ||||||
|  |  * @author gaibu | ||||||
|  |  */ | ||||||
|  | @Documented | ||||||
|  | @Target({ElementType.FIELD}) | ||||||
|  | @Retention(RetentionPolicy.RUNTIME) | ||||||
|  | @JacksonAnnotationsInside | ||||||
|  | @DesensitizeBy(handler = PasswordDesensitization.class) | ||||||
|  | public @interface PasswordDesensitize { | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 前缀保留长度 | ||||||
|  |      */ | ||||||
|  |     int prefixKeep() default 0; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 后缀保留长度 | ||||||
|  |      */ | ||||||
|  |     int suffixKeep() default 0; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 替换规则,密码; | ||||||
|  |      * | ||||||
|  |      * 比如:123456脱敏之后为****** | ||||||
|  |      */ | ||||||
|  |     String replacer() default "*"; | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -0,0 +1,42 @@ | |||||||
|  | package cn.iocoder.yudao.framework.desensitize.core.slider.annotation; | ||||||
|  |  | ||||||
|  | import cn.iocoder.yudao.framework.desensitize.core.base.annotation.DesensitizeBy; | ||||||
|  | import cn.iocoder.yudao.framework.desensitize.core.slider.handler.DefaultDesensitizationHandler; | ||||||
|  | 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; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 滑动脱敏注解 | ||||||
|  |  * | ||||||
|  |  * @author gaibu | ||||||
|  |  */ | ||||||
|  | @Documented | ||||||
|  | @Target({ElementType.FIELD, ElementType.ANNOTATION_TYPE}) | ||||||
|  | @Retention(RetentionPolicy.RUNTIME) | ||||||
|  | @JacksonAnnotationsInside | ||||||
|  | @DesensitizeBy(handler = DefaultDesensitizationHandler.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,78 @@ | |||||||
|  | package cn.iocoder.yudao.framework.desensitize.core.slider.handler; | ||||||
|  |  | ||||||
|  | import cn.iocoder.yudao.framework.desensitize.core.base.handler.DesensitizationHandler; | ||||||
|  |  | ||||||
|  | import java.lang.annotation.Annotation; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 滑动脱敏处理器抽象类,已实现通用的方法 | ||||||
|  |  * | ||||||
|  |  * @author gaibu | ||||||
|  |  */ | ||||||
|  | public abstract class AbstractDesensitizationHandler<T extends Annotation> | ||||||
|  |         implements DesensitizationHandler<T> { | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public String desensitize(String origin, T annotation) { | ||||||
|  |         int prefixKeep = getPrefixKeep(annotation); | ||||||
|  |         int suffixKeep = getSuffixKeep(annotation); | ||||||
|  |         String replacer = getReplacer(annotation); | ||||||
|  |         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) { | ||||||
|  |         StringBuilder builder = new StringBuilder(); | ||||||
|  |         for (int i = 0; i < length; i++) { | ||||||
|  |             builder.append(replacer); | ||||||
|  |         } | ||||||
|  |         return builder.toString(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 前缀保留长度 | ||||||
|  |      * | ||||||
|  |      * @param annotation 注解信息 | ||||||
|  |      * @return 前缀保留长度 | ||||||
|  |      */ | ||||||
|  |     abstract Integer getPrefixKeep(T annotation); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 后缀保留长度 | ||||||
|  |      * | ||||||
|  |      * @param annotation 注解信息 | ||||||
|  |      * @return 后缀保留长度 | ||||||
|  |      */ | ||||||
|  |     abstract Integer getSuffixKeep(T annotation); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 替换符 | ||||||
|  |      * | ||||||
|  |      * @param annotation 注解信息 | ||||||
|  |      * @return 替换符 | ||||||
|  |      */ | ||||||
|  |     abstract String getReplacer(T annotation); | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -0,0 +1,27 @@ | |||||||
|  | package cn.iocoder.yudao.framework.desensitize.core.slider.handler; | ||||||
|  |  | ||||||
|  | import cn.iocoder.yudao.framework.desensitize.core.slider.annotation.BankCardDesensitize; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * {@link BankCardDesensitize} 的脱敏处理器 | ||||||
|  |  * | ||||||
|  |  * @author gaibu | ||||||
|  |  */ | ||||||
|  | public class BankCardDesensitization extends AbstractDesensitizationHandler<BankCardDesensitize> { | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     Integer getPrefixKeep(BankCardDesensitize annotation) { | ||||||
|  |         return annotation.prefixKeep(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     Integer getSuffixKeep(BankCardDesensitize annotation) { | ||||||
|  |         return annotation.suffixKeep(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     String getReplacer(BankCardDesensitize annotation) { | ||||||
|  |         return annotation.replacer(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -0,0 +1,25 @@ | |||||||
|  | package cn.iocoder.yudao.framework.desensitize.core.slider.handler; | ||||||
|  |  | ||||||
|  | import cn.iocoder.yudao.framework.desensitize.core.slider.annotation.CarLicenseDesensitize; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * {@link CarLicenseDesensitize} 的脱敏处理器 | ||||||
|  |  * | ||||||
|  |  * @author gaibu | ||||||
|  |  */ | ||||||
|  | public class CarLicenseDesensitization extends AbstractDesensitizationHandler<CarLicenseDesensitize> { | ||||||
|  |     @Override | ||||||
|  |     Integer getPrefixKeep(CarLicenseDesensitize annotation) { | ||||||
|  |         return annotation.prefixKeep(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     Integer getSuffixKeep(CarLicenseDesensitize annotation) { | ||||||
|  |         return annotation.suffixKeep(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     String getReplacer(CarLicenseDesensitize annotation) { | ||||||
|  |         return annotation.replacer(); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -0,0 +1,27 @@ | |||||||
|  | package cn.iocoder.yudao.framework.desensitize.core.slider.handler; | ||||||
|  |  | ||||||
|  | import cn.iocoder.yudao.framework.desensitize.core.slider.annotation.ChineseNameDesensitize; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * {@link ChineseNameDesensitize} 的脱敏处理器 | ||||||
|  |  * | ||||||
|  |  * @author gaibu | ||||||
|  |  */ | ||||||
|  | public class ChineseNameDesensitization extends AbstractDesensitizationHandler<ChineseNameDesensitize> { | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     Integer getPrefixKeep(ChineseNameDesensitize annotation) { | ||||||
|  |         return annotation.prefixKeep(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     Integer getSuffixKeep(ChineseNameDesensitize annotation) { | ||||||
|  |         return annotation.suffixKeep(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     String getReplacer(ChineseNameDesensitize annotation) { | ||||||
|  |         return annotation.replacer(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -0,0 +1,25 @@ | |||||||
|  | package cn.iocoder.yudao.framework.desensitize.core.slider.handler; | ||||||
|  |  | ||||||
|  | import cn.iocoder.yudao.framework.desensitize.core.slider.annotation.SliderDesensitize; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * {@link SliderDesensitize} 的脱敏处理器 | ||||||
|  |  * | ||||||
|  |  * @author gaibu | ||||||
|  |  */ | ||||||
|  | public class DefaultDesensitizationHandler extends AbstractDesensitizationHandler<SliderDesensitize> { | ||||||
|  |     @Override | ||||||
|  |     Integer getPrefixKeep(SliderDesensitize annotation) { | ||||||
|  |         return annotation.prefixKeep(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     Integer getSuffixKeep(SliderDesensitize annotation) { | ||||||
|  |         return annotation.suffixKeep(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     String getReplacer(SliderDesensitize annotation) { | ||||||
|  |         return annotation.replacer(); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -0,0 +1,25 @@ | |||||||
|  | package cn.iocoder.yudao.framework.desensitize.core.slider.handler; | ||||||
|  |  | ||||||
|  | import cn.iocoder.yudao.framework.desensitize.core.slider.annotation.FixedPhoneDesensitize; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * {@link FixedPhoneDesensitize} 的脱敏处理器 | ||||||
|  |  * | ||||||
|  |  * @author gaibu | ||||||
|  |  */ | ||||||
|  | public class FixedPhoneDesensitization extends AbstractDesensitizationHandler<FixedPhoneDesensitize> { | ||||||
|  |     @Override | ||||||
|  |     Integer getPrefixKeep(FixedPhoneDesensitize annotation) { | ||||||
|  |         return annotation.prefixKeep(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     Integer getSuffixKeep(FixedPhoneDesensitize annotation) { | ||||||
|  |         return annotation.suffixKeep(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     String getReplacer(FixedPhoneDesensitize annotation) { | ||||||
|  |         return annotation.replacer(); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -0,0 +1,25 @@ | |||||||
|  | package cn.iocoder.yudao.framework.desensitize.core.slider.handler; | ||||||
|  |  | ||||||
|  | import cn.iocoder.yudao.framework.desensitize.core.slider.annotation.IdCardDesensitize; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * {@link IdCardDesensitize} 的脱敏处理器 | ||||||
|  |  * | ||||||
|  |  * @author gaibu | ||||||
|  |  */ | ||||||
|  | public class IdCardDesensitization extends AbstractDesensitizationHandler<IdCardDesensitize> { | ||||||
|  |     @Override | ||||||
|  |     Integer getPrefixKeep(IdCardDesensitize annotation) { | ||||||
|  |         return annotation.prefixKeep(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     Integer getSuffixKeep(IdCardDesensitize annotation) { | ||||||
|  |         return annotation.suffixKeep(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     String getReplacer(IdCardDesensitize annotation) { | ||||||
|  |         return annotation.replacer(); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -0,0 +1,26 @@ | |||||||
|  | package cn.iocoder.yudao.framework.desensitize.core.slider.handler; | ||||||
|  |  | ||||||
|  | import cn.iocoder.yudao.framework.desensitize.core.slider.annotation.MobileDesensitize; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * {@link MobileDesensitize} 的脱敏处理器 | ||||||
|  |  * | ||||||
|  |  * @author gaibu | ||||||
|  |  */ | ||||||
|  | public class MobileDesensitization extends AbstractDesensitizationHandler<MobileDesensitize> { | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     Integer getPrefixKeep(MobileDesensitize annotation) { | ||||||
|  |         return annotation.prefixKeep(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     Integer getSuffixKeep(MobileDesensitize annotation) { | ||||||
|  |         return annotation.suffixKeep(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     String getReplacer(MobileDesensitize annotation) { | ||||||
|  |         return annotation.replacer(); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -0,0 +1,25 @@ | |||||||
|  | package cn.iocoder.yudao.framework.desensitize.core.slider.handler; | ||||||
|  |  | ||||||
|  | import cn.iocoder.yudao.framework.desensitize.core.slider.annotation.PasswordDesensitize; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * {@link PasswordDesensitize} 的码脱敏处理器 | ||||||
|  |  * | ||||||
|  |  * @author gaibu | ||||||
|  |  */ | ||||||
|  | public class PasswordDesensitization extends AbstractDesensitizationHandler<PasswordDesensitize> { | ||||||
|  |     @Override | ||||||
|  |     Integer getPrefixKeep(PasswordDesensitize annotation) { | ||||||
|  |         return annotation.prefixKeep(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     Integer getSuffixKeep(PasswordDesensitize annotation) { | ||||||
|  |         return annotation.suffixKeep(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     String getReplacer(PasswordDesensitize annotation) { | ||||||
|  |         return annotation.replacer(); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -0,0 +1,98 @@ | |||||||
|  | package cn.iocoder.yudao.framework.desensitize.core; | ||||||
|  |  | ||||||
|  | import cn.iocoder.yudao.framework.common.util.json.JsonUtils; | ||||||
|  | import cn.iocoder.yudao.framework.desensitize.core.regex.annotation.EmailDesensitize; | ||||||
|  | import cn.iocoder.yudao.framework.desensitize.core.regex.annotation.RegexDesensitize; | ||||||
|  | import cn.iocoder.yudao.framework.desensitize.core.annotation.Address; | ||||||
|  | import cn.iocoder.yudao.framework.desensitize.core.slider.annotation.BankCardDesensitize; | ||||||
|  | import cn.iocoder.yudao.framework.desensitize.core.slider.annotation.CarLicenseDesensitize; | ||||||
|  | import cn.iocoder.yudao.framework.desensitize.core.slider.annotation.ChineseNameDesensitize; | ||||||
|  | import cn.iocoder.yudao.framework.desensitize.core.slider.annotation.FixedPhoneDesensitize; | ||||||
|  | import cn.iocoder.yudao.framework.desensitize.core.slider.annotation.IdCardDesensitize; | ||||||
|  | import cn.iocoder.yudao.framework.desensitize.core.slider.annotation.PasswordDesensitize; | ||||||
|  | import cn.iocoder.yudao.framework.desensitize.core.slider.annotation.MobileDesensitize; | ||||||
|  | import cn.iocoder.yudao.framework.desensitize.core.slider.annotation.SliderDesensitize; | ||||||
|  | import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; | ||||||
|  | import lombok.Data; | ||||||
|  | import org.junit.jupiter.api.Test; | ||||||
|  |  | ||||||
|  | import static org.junit.jupiter.api.Assertions.*; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * {@link DesensitizeTest} 的单元测试 | ||||||
|  |  */ | ||||||
|  | public class DesensitizeTest extends BaseMockitoUnitTest { | ||||||
|  |  | ||||||
|  |     @Test | ||||||
|  |     public void test() { | ||||||
|  |         // 准备参数 | ||||||
|  |         DesensitizeDemo desensitizeDemo = new DesensitizeDemo(); | ||||||
|  |         desensitizeDemo.setNickname("芋道源码"); | ||||||
|  |         desensitizeDemo.setBankCard("9988002866797031"); | ||||||
|  |         desensitizeDemo.setCarLicense("粤A66666"); | ||||||
|  |         desensitizeDemo.setFixedPhone("01086551122"); | ||||||
|  |         desensitizeDemo.setIdCard("530321199204074611"); | ||||||
|  |         desensitizeDemo.setPassword("123456"); | ||||||
|  |         desensitizeDemo.setPhoneNumber("13248765917"); | ||||||
|  |         desensitizeDemo.setSlider1("ABCDEFG"); | ||||||
|  |         desensitizeDemo.setSlider2("ABCDEFG"); | ||||||
|  |         desensitizeDemo.setSlider3("ABCDEFG"); | ||||||
|  |         desensitizeDemo.setEmail("1@email.com"); | ||||||
|  |         desensitizeDemo.setRegex("你好,我是芋道源码"); | ||||||
|  |         desensitizeDemo.setAddress("北京市海淀区上地十街10号"); | ||||||
|  |         desensitizeDemo.setOrigin("芋道源码"); | ||||||
|  |  | ||||||
|  |         // 调用 | ||||||
|  |         DesensitizeDemo d = JsonUtils.parseObject(JsonUtils.toJsonString(desensitizeDemo), DesensitizeDemo.class); | ||||||
|  |         // 断言 | ||||||
|  |         assertNotNull(d); | ||||||
|  |         assertEquals("芋***", d.getNickname()); | ||||||
|  |         assertEquals("998800********31", d.getBankCard()); | ||||||
|  |         assertEquals("粤A6***6", d.getCarLicense()); | ||||||
|  |         assertEquals("0108*****22", d.getFixedPhone()); | ||||||
|  |         assertEquals("530321**********11", d.getIdCard()); | ||||||
|  |         assertEquals("******", d.getPassword()); | ||||||
|  |         assertEquals("132****5917", d.getPhoneNumber()); | ||||||
|  |         assertEquals("#######", d.getSlider1()); | ||||||
|  |         assertEquals("ABC*EFG", d.getSlider2()); | ||||||
|  |         assertEquals("*******", d.getSlider3()); | ||||||
|  |         assertEquals("1****@email.com", d.getEmail()); | ||||||
|  |         assertEquals("你好,我是*", d.getRegex()); | ||||||
|  |         assertEquals("北京市海淀区上地十街10号*", d.getAddress()); | ||||||
|  |         assertEquals("芋道源码", d.getOrigin()); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Data | ||||||
|  |     public static class DesensitizeDemo { | ||||||
|  |  | ||||||
|  |         @ChineseNameDesensitize | ||||||
|  |         private String nickname; | ||||||
|  |         @BankCardDesensitize | ||||||
|  |         private String bankCard; | ||||||
|  |         @CarLicenseDesensitize | ||||||
|  |         private String carLicense; | ||||||
|  |         @FixedPhoneDesensitize | ||||||
|  |         private String fixedPhone; | ||||||
|  |         @IdCardDesensitize | ||||||
|  |         private String idCard; | ||||||
|  |         @PasswordDesensitize | ||||||
|  |         private String password; | ||||||
|  |         @MobileDesensitize | ||||||
|  |         private String phoneNumber; | ||||||
|  |         @SliderDesensitize(prefixKeep = 6, suffixKeep = 1, replacer = "#") | ||||||
|  |         private String slider1; | ||||||
|  |         @SliderDesensitize(prefixKeep = 3, suffixKeep = 3) | ||||||
|  |         private String slider2; | ||||||
|  |         @SliderDesensitize(prefixKeep = 10) | ||||||
|  |         private String slider3; | ||||||
|  |         @EmailDesensitize | ||||||
|  |         private String email; | ||||||
|  |         @RegexDesensitize(regex = "芋道源码", replacer = "*") | ||||||
|  |         private String regex; | ||||||
|  |         @Address | ||||||
|  |         private String address; | ||||||
|  |         private String origin; | ||||||
|  |  | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -0,0 +1,30 @@ | |||||||
|  | package cn.iocoder.yudao.framework.desensitize.core.annotation; | ||||||
|  |  | ||||||
|  | import cn.iocoder.yudao.framework.desensitize.core.DesensitizeTest; | ||||||
|  | import cn.iocoder.yudao.framework.desensitize.core.base.annotation.DesensitizeBy; | ||||||
|  | import cn.iocoder.yudao.framework.desensitize.core.handler.AddressHandler; | ||||||
|  | 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; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 地址 | ||||||
|  |  * | ||||||
|  |  * 用于 {@link DesensitizeTest} 测试使用 | ||||||
|  |  * | ||||||
|  |  * @author gaibu | ||||||
|  |  */ | ||||||
|  | @Documented | ||||||
|  | @Target({ElementType.FIELD}) | ||||||
|  | @Retention(RetentionPolicy.RUNTIME) | ||||||
|  | @JacksonAnnotationsInside | ||||||
|  | @DesensitizeBy(handler = AddressHandler.class) | ||||||
|  | public @interface Address { | ||||||
|  |  | ||||||
|  |     String replacer() default "*"; | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -0,0 +1,19 @@ | |||||||
|  | package cn.iocoder.yudao.framework.desensitize.core.handler; | ||||||
|  |  | ||||||
|  | import cn.iocoder.yudao.framework.desensitize.core.DesensitizeTest; | ||||||
|  | import cn.iocoder.yudao.framework.desensitize.core.base.handler.DesensitizationHandler; | ||||||
|  | import cn.iocoder.yudao.framework.desensitize.core.annotation.Address; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * {@link Address} 的脱敏处理器 | ||||||
|  |  * | ||||||
|  |  * 用于 {@link DesensitizeTest} 测试使用 | ||||||
|  |  */ | ||||||
|  | public class AddressHandler implements DesensitizationHandler<Address> { | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public String desensitize(String origin, Address annotation) { | ||||||
|  |         return origin + annotation.replacer(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -1 +1,4 @@ | |||||||
|  | /** | ||||||
|  |  * Web 框架,全局异常、API 日志等 | ||||||
|  |  */ | ||||||
| package cn.iocoder.yudao.framework; | package cn.iocoder.yudao.framework; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 芋道源码
					芋道源码