mirror of
https://gitee.com/hhyykk/ipms-sjy.git
synced 2025-07-24 16:05:08 +08:00
feat: 脱敏组件代码规范更新
This commit is contained in:
@ -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>脱敏组件</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,38 @@
|
||||
package cn.iocoder.yudao.framework.desensitize.core.base;
|
||||
|
||||
import cn.hutool.core.util.ReflectUtil;
|
||||
import cn.iocoder.yudao.framework.desensitize.core.base.handler.DesensitizationHandler;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* 脱敏处理器 Holder
|
||||
*
|
||||
* @author gaibu
|
||||
*/
|
||||
public class DesensitizationHandlerFactory {
|
||||
|
||||
/**
|
||||
* handler 缓存,默认初始化内置的处理器
|
||||
*/
|
||||
private static final Map<Class<? extends DesensitizationHandler>, DesensitizationHandler> HANDLER_MAP = new ConcurrentHashMap<Class<? extends DesensitizationHandler>, DesensitizationHandler>();
|
||||
|
||||
public static DesensitizationHandler getDesensitizationHandler(Class<? extends DesensitizationHandler> clazz) {
|
||||
DesensitizationHandler handler = HANDLER_MAP.get(clazz);
|
||||
if (handler != null) {
|
||||
return handler;
|
||||
}
|
||||
synchronized (DesensitizationHandlerFactory.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,30 @@
|
||||
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 {
|
||||
|
||||
/**
|
||||
* 脱敏处理器
|
||||
*/
|
||||
Class<? extends DesensitizationHandler> handler();
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package cn.iocoder.yudao.framework.desensitize.core.base.handler;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
|
||||
/**
|
||||
* 脱敏处理器接口
|
||||
*/
|
||||
public interface DesensitizationHandler<T extends Annotation> {
|
||||
|
||||
/**
|
||||
* 脱敏
|
||||
*
|
||||
* @param origin 原始字符串
|
||||
* @param annotation 注解信息
|
||||
* @return 脱敏后的字符串
|
||||
*/
|
||||
String desensitize(String origin, T annotation);
|
||||
|
||||
}
|
@ -0,0 +1,88 @@
|
||||
package cn.iocoder.yudao.framework.desensitize.core.base.serializer;
|
||||
|
||||
import cn.hutool.core.annotation.AnnotationUtil;
|
||||
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 cn.iocoder.yudao.framework.desensitize.core.base.DesensitizationHandlerFactory;
|
||||
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 lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
/**
|
||||
* 脱敏序列化器
|
||||
*
|
||||
* @author gaibu
|
||||
*/
|
||||
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) throws JsonMappingException {
|
||||
DesensitizeBy annotation = beanProperty.getAnnotation(DesensitizeBy.class);
|
||||
if (annotation == null) {
|
||||
return this;
|
||||
}
|
||||
StringDesensitizeSerializer serializer = new StringDesensitizeSerializer();
|
||||
serializer.setDesensitizationHandler(DesensitizationHandlerFactory.getDesensitizationHandler(annotation.handler()));
|
||||
return serializer;
|
||||
}
|
||||
|
||||
@Override
|
||||
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 gen JsonGenerator
|
||||
* @return 字段
|
||||
*/
|
||||
private Field getField(JsonGenerator gen) {
|
||||
String currentName = gen.getOutputContext().getCurrentName();
|
||||
Object currentValue = gen.getCurrentValue();
|
||||
Class<?> currentValueClass = currentValue.getClass();
|
||||
return ReflectUtil.getField(currentValueClass, currentName);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
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,37 @@
|
||||
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,37 @@
|
||||
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,22 @@
|
||||
package cn.iocoder.yudao.framework.desensitize.core.regex.handler;
|
||||
|
||||
import cn.iocoder.yudao.framework.desensitize.core.regex.annotation.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,21 @@
|
||||
package cn.iocoder.yudao.framework.desensitize.core.regex.handler;
|
||||
|
||||
import cn.iocoder.yudao.framework.desensitize.core.regex.annotation.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 BankCard {
|
||||
|
||||
/**
|
||||
* 前缀保留长度
|
||||
*/
|
||||
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 CarLicense {
|
||||
|
||||
/**
|
||||
* 前缀保留长度
|
||||
*/
|
||||
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 ChineseName {
|
||||
|
||||
/**
|
||||
* 前缀保留长度
|
||||
*/
|
||||
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 FixedPhone {
|
||||
|
||||
/**
|
||||
* 前缀保留长度
|
||||
*/
|
||||
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 IdCard {
|
||||
|
||||
/**
|
||||
* 前缀保留长度
|
||||
*/
|
||||
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.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 Password {
|
||||
|
||||
/**
|
||||
* 前缀保留长度
|
||||
*/
|
||||
int prefixKeep() default 0;
|
||||
|
||||
/**
|
||||
* 后缀保留长度
|
||||
*/
|
||||
int suffixKeep() default 0;
|
||||
|
||||
/**
|
||||
* 替换规则,密码;比如:123456脱敏之后为******
|
||||
*/
|
||||
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.PhoneNumberDesensitization;
|
||||
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 = PhoneNumberDesensitization.class)
|
||||
public @interface PhoneNumber {
|
||||
|
||||
/**
|
||||
* 前缀保留长度
|
||||
*/
|
||||
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.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 Slider {
|
||||
|
||||
/**
|
||||
* 后缀保留长度
|
||||
*/
|
||||
int suffixKeep() default 0;
|
||||
|
||||
/**
|
||||
* 替换规则,会将前缀后缀保留后,全部替换成 replacer
|
||||
* 例如:prefixKeep = 1; suffixKeep = 2; replacer = "*";
|
||||
* 原始字符串 123456
|
||||
* 脱敏后 1***56
|
||||
*/
|
||||
String replacer() default "*";
|
||||
|
||||
/**
|
||||
* 前缀保留长度
|
||||
*/
|
||||
int prefixKeep() default 0;
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
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 annotation 注解信息
|
||||
* @return 前缀保留长度
|
||||
*/
|
||||
abstract Integer getPrefixKeep(T annotation);
|
||||
|
||||
/**
|
||||
* 后缀保留长度
|
||||
*
|
||||
* @param annotation 注解信息
|
||||
* @return 后缀保留长度
|
||||
*/
|
||||
abstract Integer getSuffixKeep(T annotation);
|
||||
|
||||
/**
|
||||
* 替换符
|
||||
*
|
||||
* @param annotation 注解信息
|
||||
* @return 替换符
|
||||
*/
|
||||
abstract String getReplacer(T annotation);
|
||||
|
||||
/**
|
||||
* 根据长度循环构建替换符
|
||||
*
|
||||
* @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();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
package cn.iocoder.yudao.framework.desensitize.core.slider.handler;
|
||||
|
||||
import cn.iocoder.yudao.framework.desensitize.core.slider.annotation.BankCard;
|
||||
|
||||
/**
|
||||
* 银行卡脱敏处理器
|
||||
*
|
||||
* @author gaibu
|
||||
*/
|
||||
public class BankCardDesensitization extends AbstractDesensitizationHandler<BankCard> {
|
||||
|
||||
@Override
|
||||
Integer getPrefixKeep(BankCard annotation) {
|
||||
return annotation.prefixKeep();
|
||||
}
|
||||
|
||||
@Override
|
||||
Integer getSuffixKeep(BankCard annotation) {
|
||||
return annotation.suffixKeep();
|
||||
}
|
||||
|
||||
@Override
|
||||
String getReplacer(BankCard 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.CarLicense;
|
||||
|
||||
/**
|
||||
* 车牌号脱敏处理器
|
||||
*
|
||||
* @author gaibu
|
||||
*/
|
||||
public class CarLicenseDesensitization extends AbstractDesensitizationHandler<CarLicense> {
|
||||
@Override
|
||||
Integer getPrefixKeep(CarLicense annotation) {
|
||||
return annotation.prefixKeep();
|
||||
}
|
||||
|
||||
@Override
|
||||
Integer getSuffixKeep(CarLicense annotation) {
|
||||
return annotation.suffixKeep();
|
||||
}
|
||||
|
||||
@Override
|
||||
String getReplacer(CarLicense 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.ChineseName;
|
||||
|
||||
/**
|
||||
* 中文姓名脱敏处理器
|
||||
*
|
||||
* @author gaibu
|
||||
*/
|
||||
public class ChineseNameDesensitization extends AbstractDesensitizationHandler<ChineseName> {
|
||||
@Override
|
||||
Integer getPrefixKeep(ChineseName annotation) {
|
||||
return annotation.prefixKeep();
|
||||
}
|
||||
|
||||
@Override
|
||||
Integer getSuffixKeep(ChineseName annotation) {
|
||||
return annotation.suffixKeep();
|
||||
}
|
||||
|
||||
@Override
|
||||
String getReplacer(ChineseName 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.Slider;
|
||||
|
||||
/**
|
||||
* 滑动脱敏处理器
|
||||
*
|
||||
* @author gaibu
|
||||
*/
|
||||
public class DefaultDesensitizationHandler extends AbstractDesensitizationHandler<Slider> {
|
||||
@Override
|
||||
Integer getPrefixKeep(Slider annotation) {
|
||||
return annotation.prefixKeep();
|
||||
}
|
||||
|
||||
@Override
|
||||
Integer getSuffixKeep(Slider annotation) {
|
||||
return annotation.suffixKeep();
|
||||
}
|
||||
|
||||
@Override
|
||||
String getReplacer(Slider 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.FixedPhone;
|
||||
|
||||
/**
|
||||
* 固定电话脱敏处理器
|
||||
*
|
||||
* @author gaibu
|
||||
*/
|
||||
public class FixedPhoneDesensitization extends AbstractDesensitizationHandler<FixedPhone> {
|
||||
@Override
|
||||
Integer getPrefixKeep(FixedPhone annotation) {
|
||||
return annotation.prefixKeep();
|
||||
}
|
||||
|
||||
@Override
|
||||
Integer getSuffixKeep(FixedPhone annotation) {
|
||||
return annotation.suffixKeep();
|
||||
}
|
||||
|
||||
@Override
|
||||
String getReplacer(FixedPhone 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.IdCard;
|
||||
|
||||
/**
|
||||
* 身份证脱敏处理器
|
||||
*
|
||||
* @author gaibu
|
||||
*/
|
||||
public class IdCardDesensitization extends AbstractDesensitizationHandler<IdCard> {
|
||||
@Override
|
||||
Integer getPrefixKeep(IdCard annotation) {
|
||||
return annotation.prefixKeep();
|
||||
}
|
||||
|
||||
@Override
|
||||
Integer getSuffixKeep(IdCard annotation) {
|
||||
return annotation.suffixKeep();
|
||||
}
|
||||
|
||||
@Override
|
||||
String getReplacer(IdCard 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.Password;
|
||||
|
||||
/**
|
||||
* 密码脱敏处理器
|
||||
*
|
||||
* @author gaibu
|
||||
*/
|
||||
public class PasswordDesensitization extends AbstractDesensitizationHandler<Password> {
|
||||
@Override
|
||||
Integer getPrefixKeep(Password annotation) {
|
||||
return annotation.prefixKeep();
|
||||
}
|
||||
|
||||
@Override
|
||||
Integer getSuffixKeep(Password annotation) {
|
||||
return annotation.suffixKeep();
|
||||
}
|
||||
|
||||
@Override
|
||||
String getReplacer(Password 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.PhoneNumber;
|
||||
|
||||
/**
|
||||
* 手机号脱敏处理器
|
||||
*
|
||||
* @author gaibu
|
||||
*/
|
||||
public class PhoneNumberDesensitization extends AbstractDesensitizationHandler<PhoneNumber> {
|
||||
|
||||
@Override
|
||||
Integer getPrefixKeep(PhoneNumber annotation) {
|
||||
return annotation.prefixKeep();
|
||||
}
|
||||
|
||||
@Override
|
||||
Integer getSuffixKeep(PhoneNumber annotation) {
|
||||
return annotation.suffixKeep();
|
||||
}
|
||||
|
||||
@Override
|
||||
String getReplacer(PhoneNumber annotation) {
|
||||
return annotation.replacer();
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user