diff --git a/ballcat-common/ballcat-common-core/src/main/java/com/hccake/ballcat/common/core/desensite/DesensitizationHandler.java b/ballcat-common/ballcat-common-core/src/main/java/com/hccake/ballcat/common/core/desensite/DesensitizationHandler.java new file mode 100644 index 00000000..5dda7457 --- /dev/null +++ b/ballcat-common/ballcat-common-core/src/main/java/com/hccake/ballcat/common/core/desensite/DesensitizationHandler.java @@ -0,0 +1,26 @@ +package com.hccake.ballcat.common.core.desensite; + +/** + * 脱敏处理器 + * + * TODO 复用中央脱敏和正则脱敏,在注解中自定义属性而不必实现一个 Handler + * + * @author Hccake 2021/1/22 + * @version 1.0 + */ +public interface DesensitizationHandler { + + /** + * 脱敏类型 + * @return 类型 + */ + String getType(); + + /** + * 脱敏处理 + * @param origin 原始字符串 + * @return 脱敏处理后的字符串 + */ + String handle(String origin); + +} diff --git a/ballcat-common/ballcat-common-core/src/main/java/com/hccake/ballcat/common/core/desensite/DesensitizationHandlerHolder.java b/ballcat-common/ballcat-common-core/src/main/java/com/hccake/ballcat/common/core/desensite/DesensitizationHandlerHolder.java new file mode 100644 index 00000000..47f7abfe --- /dev/null +++ b/ballcat-common/ballcat-common-core/src/main/java/com/hccake/ballcat/common/core/desensite/DesensitizationHandlerHolder.java @@ -0,0 +1,25 @@ +package com.hccake.ballcat.common.core.desensite; + +import java.util.Map; +import java.util.ServiceLoader; +import java.util.concurrent.ConcurrentHashMap; + +/** + * 脱敏处理器持有者,使用SPI方式加载所有的脱敏处理器,便于用户扩展处理 + * + * @author Hccake 2021/1/22 + * @version 1.0 + */ +public class DesensitizationHandlerHolder { + + public final static Map TYPE_MAPS = new ConcurrentHashMap<>(); + + static { + // SPI 加载所有的脱敏类型处理 + ServiceLoader loadedDrivers = ServiceLoader.load(DesensitizationHandler.class); + for (DesensitizationHandler desensitizationHandler : loadedDrivers) { + TYPE_MAPS.put(desensitizationHandler.getType(), desensitizationHandler); + } + } + +} diff --git a/ballcat-common/ballcat-common-core/src/main/java/com/hccake/ballcat/common/core/desensite/DesensitizationTypeConstant.java b/ballcat-common/ballcat-common-core/src/main/java/com/hccake/ballcat/common/core/desensite/DesensitizationTypeConstant.java new file mode 100644 index 00000000..c3f35e54 --- /dev/null +++ b/ballcat-common/ballcat-common-core/src/main/java/com/hccake/ballcat/common/core/desensite/DesensitizationTypeConstant.java @@ -0,0 +1,56 @@ +package com.hccake.ballcat.common.core.desensite; + +/** + * 默认的一些脱敏方式 + * + * @author Hccake 2021/1/22 + * @version 1.0 + */ +public final class DesensitizationTypeConstant { + + private DesensitizationTypeConstant() { + } + + /** + * 全脱敏 + * @see com.hccake.ballcat.common.core.desensite.handler.AllMaskDesensitizationHandler + */ + public static final String ALL_MASK = "ALL_MASK"; + + /** + * 银行卡脱敏 + * @see com.hccake.ballcat.common.core.desensite.handler.BankCardNODesensitizationHandler + */ + public static final String BANK_CARD_NO = "BANK_CARD_NO"; + + /** + * 邮箱脱敏 + * @see com.hccake.ballcat.common.core.desensite.handler.EmailDesensitizationHandler + */ + public static final String EMAIL = "EMAIL"; + + /** + * 加密后的密码脱敏 + * @see com.hccake.ballcat.common.core.desensite.handler.EncryptedPasswordDesensitizationHandler + */ + public static final String ENCRYPTED_PASSWORD = "ENCRYPTED_PASSWORD"; + + /** + * 定长脱敏,总是返回定长的数据值 + * @see com.hccake.ballcat.common.core.desensite.handler.FixedLengthDesensitizationHandler + */ + public static final String FIXED_LENGTH = "FIXED_LENGTH"; + + /** + * 身份证号脱敏 + * @see com.hccake.ballcat.common.core.desensite.handler.IDCardNODesensitizationHandler + */ + public static final String ID_CARD_NO = "ID_CARD_NO"; + + /** + * 手机号脱敏 + * @see com.hccake.ballcat.common.core.desensite.handler.PhoneNumberDesensitizationHandler + */ + public static final String PHONE_NUMBER = "PHONE_NUMBER"; + +} diff --git a/ballcat-common/ballcat-common-core/src/main/java/com/hccake/ballcat/common/core/desensite/JsonDesensitize.java b/ballcat-common/ballcat-common-core/src/main/java/com/hccake/ballcat/common/core/desensite/JsonDesensitize.java new file mode 100644 index 00000000..3d556dc8 --- /dev/null +++ b/ballcat-common/ballcat-common-core/src/main/java/com/hccake/ballcat/common/core/desensite/JsonDesensitize.java @@ -0,0 +1,27 @@ +package com.hccake.ballcat.common.core.desensite; + +import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; + +import java.lang.annotation.*; + +/** + * Jackson Filed 序列化脱敏注解 + * @author Hccake 2021/1/22 + * @version 1.0 + */ +@Target({ ElementType.FIELD }) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@JacksonAnnotationsInside +@JsonSerialize(using = JsonDesensitizeSerializer.class) +public @interface JsonDesensitize { + + /** + * 脱敏类型,用于指定脱敏处理器 + * @see DesensitizationHandler#getType() + * @return type + */ + String type(); + +} diff --git a/ballcat-common/ballcat-common-core/src/main/java/com/hccake/ballcat/common/core/desensite/JsonDesensitizeSerializer.java b/ballcat-common/ballcat-common-core/src/main/java/com/hccake/ballcat/common/core/desensite/JsonDesensitizeSerializer.java new file mode 100644 index 00000000..b9483817 --- /dev/null +++ b/ballcat-common/ballcat-common-core/src/main/java/com/hccake/ballcat/common/core/desensite/JsonDesensitizeSerializer.java @@ -0,0 +1,52 @@ +package com.hccake.ballcat.common.core.desensite; + +import cn.hutool.core.lang.Assert; +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 java.io.IOException; +import java.util.Objects; + +/** + * Jackson脱敏处理序列化器 + * + * @author Hccake 2021/1/22 + * @version 1.0 + */ +public class JsonDesensitizeSerializer extends JsonSerializer implements ContextualSerializer { + + private JsonDesensitize jsonDesensitize; + + @Override + public void serialize(String value, JsonGenerator jsonGenerator, SerializerProvider serializers) + throws IOException { + String type = jsonDesensitize.type(); + DesensitizationHandler desensitizationHandler = DesensitizationHandlerHolder.TYPE_MAPS.get(type); + Assert.notNull(desensitizationHandler, "DesensitizationHandler can not be Null"); + jsonGenerator.writeString(desensitizationHandler.handle(value)); + } + + @Override + public JsonSerializer createContextual(SerializerProvider serializerProvider, BeanProperty beanProperty) + throws JsonMappingException { + if (beanProperty != null) { + if (Objects.equals(beanProperty.getType().getRawClass(), String.class)) { + JsonDesensitize jsonDesensitize = beanProperty.getAnnotation(JsonDesensitize.class); + if (jsonDesensitize == null) { + jsonDesensitize = beanProperty.getContextAnnotation(JsonDesensitize.class); + } + if (jsonDesensitize != null) { + this.jsonDesensitize = jsonDesensitize; + return this; + } + } + return serializerProvider.findValueSerializer(beanProperty.getType(), beanProperty); + } + return serializerProvider.findNullValueSerializer(null); + } + +} diff --git a/ballcat-common/ballcat-common-core/src/main/java/com/hccake/ballcat/common/core/desensite/handler/AbstractCenterDesensitizationHandler.java b/ballcat-common/ballcat-common-core/src/main/java/com/hccake/ballcat/common/core/desensite/handler/AbstractCenterDesensitizationHandler.java new file mode 100644 index 00000000..0ddad5ff --- /dev/null +++ b/ballcat-common/ballcat-common-core/src/main/java/com/hccake/ballcat/common/core/desensite/handler/AbstractCenterDesensitizationHandler.java @@ -0,0 +1,61 @@ +package com.hccake.ballcat.common.core.desensite.handler; + +import com.hccake.ballcat.common.core.desensite.DesensitizationHandler; +import lombok.Getter; + +/** + * 中间脱敏处理器类型,两边各展示部分明文数据 + * + * @author Hccake 2021/1/22 + * @version 1.0 + */ +@Getter +public abstract class AbstractCenterDesensitizationHandler implements DesensitizationHandler { + + private final String type; + + private final int leftPlainTextLen; + + private final int rightPlainTextLen; + + private final String maskString; + + public AbstractCenterDesensitizationHandler(String type, int leftPlainTextLen, int rightPlainTextLen) { + this(type, leftPlainTextLen, rightPlainTextLen, "*"); + } + + public AbstractCenterDesensitizationHandler(String type, int leftPlainTextLen, int rightPlainTextLen, + String maskString) { + this.type = type; + this.leftPlainTextLen = leftPlainTextLen; + this.rightPlainTextLen = rightPlainTextLen; + this.maskString = maskString; + } + + /** + * 脱敏处理 + * @param origin 原始字符串 + * @return 脱敏处理后的字符串 + */ + @Override + public String handle(String origin) { + if (origin == null) { + return null; + } + StringBuilder sb = new StringBuilder(); + + char[] chars = origin.toCharArray(); + int length = chars.length; + for (int i = 0; i < length; i++) { + // 明文位内则明文显示 + if (i < leftPlainTextLen || i > (length - rightPlainTextLen - 1)) { + sb.append(chars[i]); + } + else { + sb.append(maskString); + } + } + return sb.toString(); + } + +} diff --git a/ballcat-common/ballcat-common-core/src/main/java/com/hccake/ballcat/common/core/desensite/handler/AbstractRegexDesensitizationHandler.java b/ballcat-common/ballcat-common-core/src/main/java/com/hccake/ballcat/common/core/desensite/handler/AbstractRegexDesensitizationHandler.java new file mode 100644 index 00000000..7f91c3f4 --- /dev/null +++ b/ballcat-common/ballcat-common-core/src/main/java/com/hccake/ballcat/common/core/desensite/handler/AbstractRegexDesensitizationHandler.java @@ -0,0 +1,37 @@ +package com.hccake.ballcat.common.core.desensite.handler; + +import com.hccake.ballcat.common.core.desensite.DesensitizationHandler; +import lombok.Getter; + +/** + * 正则替换脱敏处理器类型 + * + * @author Hccake 2021/1/22 + * @version 1.0 + */ +@Getter +public abstract class AbstractRegexDesensitizationHandler implements DesensitizationHandler { + + private final String type; + + private final String regex; + + private final String replacement; + + public AbstractRegexDesensitizationHandler(String type, String regex, String replacement) { + this.type = type; + this.regex = regex; + this.replacement = replacement; + } + + /** + * 脱敏处理 + * @param origin 原始字符串 + * @return 脱敏处理后的字符串 + */ + @Override + public String handle(String origin) { + return origin.replaceAll(regex, replacement); + } + +} diff --git a/ballcat-common/ballcat-common-core/src/main/java/com/hccake/ballcat/common/core/desensite/handler/AllMaskDesensitizationHandler.java b/ballcat-common/ballcat-common-core/src/main/java/com/hccake/ballcat/common/core/desensite/handler/AllMaskDesensitizationHandler.java new file mode 100644 index 00000000..c8e12aac --- /dev/null +++ b/ballcat-common/ballcat-common-core/src/main/java/com/hccake/ballcat/common/core/desensite/handler/AllMaskDesensitizationHandler.java @@ -0,0 +1,17 @@ +package com.hccake.ballcat.common.core.desensite.handler; + +import com.hccake.ballcat.common.core.desensite.DesensitizationTypeConstant; + +/** + * 【全部】所有字符全部脱敏,保留原始位数不变 eg. 123456789 -> ********* + * + * @author Hccake 2021/1/22 + * @version 1.0 + */ +public class AllMaskDesensitizationHandler extends AbstractCenterDesensitizationHandler { + + public AllMaskDesensitizationHandler() { + super(DesensitizationTypeConstant.ALL_MASK, 0, 0); + } + +} diff --git a/ballcat-common/ballcat-common-core/src/main/java/com/hccake/ballcat/common/core/desensite/handler/BankCardNODesensitizationHandler.java b/ballcat-common/ballcat-common-core/src/main/java/com/hccake/ballcat/common/core/desensite/handler/BankCardNODesensitizationHandler.java new file mode 100644 index 00000000..b9f8b8eb --- /dev/null +++ b/ballcat-common/ballcat-common-core/src/main/java/com/hccake/ballcat/common/core/desensite/handler/BankCardNODesensitizationHandler.java @@ -0,0 +1,17 @@ +package com.hccake.ballcat.common.core.desensite.handler; + +import com.hccake.ballcat.common.core.desensite.DesensitizationTypeConstant; + +/** + * 【银行卡号】, 前6位和后4位不脱敏,中间脱敏 eg. 330150******1234 + * + * @author Hccake 2021/1/22 + * @version 1.0 + */ +public class BankCardNODesensitizationHandler extends AbstractCenterDesensitizationHandler { + + public BankCardNODesensitizationHandler() { + super(DesensitizationTypeConstant.BANK_CARD_NO, 6, 4); + } + +} diff --git a/ballcat-common/ballcat-common-core/src/main/java/com/hccake/ballcat/common/core/desensite/handler/EmailDesensitizationHandler.java b/ballcat-common/ballcat-common-core/src/main/java/com/hccake/ballcat/common/core/desensite/handler/EmailDesensitizationHandler.java new file mode 100644 index 00000000..dc0d6292 --- /dev/null +++ b/ballcat-common/ballcat-common-core/src/main/java/com/hccake/ballcat/common/core/desensite/handler/EmailDesensitizationHandler.java @@ -0,0 +1,17 @@ +package com.hccake.ballcat.common.core.desensite.handler; + +import com.hccake.ballcat.common.core.desensite.DesensitizationTypeConstant; + +/** + * 【邮箱】脱敏,保留邮箱第一个字符和'@'之后的原文显示,中间的显示为4个* eg. 12@qq.com -> 1****@qq.com + * + * @author Hccake 2021/1/22 + * @version 1.0 + */ +public class EmailDesensitizationHandler extends AbstractRegexDesensitizationHandler { + + public EmailDesensitizationHandler() { + super(DesensitizationTypeConstant.EMAIL, "(^\\w)[^@]*(@.*$)", "$1****$2"); + } + +} diff --git a/ballcat-common/ballcat-common-core/src/main/java/com/hccake/ballcat/common/core/desensite/handler/EncryptedPasswordDesensitizationHandler.java b/ballcat-common/ballcat-common-core/src/main/java/com/hccake/ballcat/common/core/desensite/handler/EncryptedPasswordDesensitizationHandler.java new file mode 100644 index 00000000..55d49072 --- /dev/null +++ b/ballcat-common/ballcat-common-core/src/main/java/com/hccake/ballcat/common/core/desensite/handler/EncryptedPasswordDesensitizationHandler.java @@ -0,0 +1,17 @@ +package com.hccake.ballcat.common.core.desensite.handler; + +import com.hccake.ballcat.common.core.desensite.DesensitizationTypeConstant; + +/** + * 【加密后的密码脱敏】 + * + * @author Hccake 2021/1/23 + * @version 1.0 + */ +public class EncryptedPasswordDesensitizationHandler extends AbstractCenterDesensitizationHandler { + + public EncryptedPasswordDesensitizationHandler() { + super(DesensitizationTypeConstant.ENCRYPTED_PASSWORD, 3, 2); + } + +} diff --git a/ballcat-common/ballcat-common-core/src/main/java/com/hccake/ballcat/common/core/desensite/handler/FixedLengthDesensitizationHandler.java b/ballcat-common/ballcat-common-core/src/main/java/com/hccake/ballcat/common/core/desensite/handler/FixedLengthDesensitizationHandler.java new file mode 100644 index 00000000..ecda7ce5 --- /dev/null +++ b/ballcat-common/ballcat-common-core/src/main/java/com/hccake/ballcat/common/core/desensite/handler/FixedLengthDesensitizationHandler.java @@ -0,0 +1,33 @@ +package com.hccake.ballcat.common.core.desensite.handler; + +import com.hccake.ballcat.common.core.desensite.DesensitizationHandler; +import com.hccake.ballcat.common.core.desensite.DesensitizationTypeConstant; + +/** + * 【固定长度】,不管原文是什么,一律返回6个* eg. ****** + * + * @author Hccake 2021/1/22 + * @version 1.0 + */ +public class FixedLengthDesensitizationHandler implements DesensitizationHandler { + + /** + * 脱敏类型 + * @return 类型 + */ + @Override + public String getType() { + return DesensitizationTypeConstant.FIXED_LENGTH; + } + + /** + * 脱敏处理 + * @param origin 原始字符串 + * @return 脱敏处理后的字符串 + */ + @Override + public String handle(String origin) { + return "******"; + } + +} diff --git a/ballcat-common/ballcat-common-core/src/main/java/com/hccake/ballcat/common/core/desensite/handler/IDCardNODesensitizationHandler.java b/ballcat-common/ballcat-common-core/src/main/java/com/hccake/ballcat/common/core/desensite/handler/IDCardNODesensitizationHandler.java new file mode 100644 index 00000000..1c32c80b --- /dev/null +++ b/ballcat-common/ballcat-common-core/src/main/java/com/hccake/ballcat/common/core/desensite/handler/IDCardNODesensitizationHandler.java @@ -0,0 +1,17 @@ +package com.hccake.ballcat.common.core.desensite.handler; + +import com.hccake.ballcat.common.core.desensite.DesensitizationTypeConstant; + +/** + * 【身份证号】年月日脱敏,前6后4不脱敏 eg. 655356*******1234 + * + * @author Hccake 2021/1/22 + * @version 1.0 + */ +public class IDCardNODesensitizationHandler extends AbstractCenterDesensitizationHandler { + + public IDCardNODesensitizationHandler() { + super(DesensitizationTypeConstant.ID_CARD_NO, 6, 4); + } + +} diff --git a/ballcat-common/ballcat-common-core/src/main/java/com/hccake/ballcat/common/core/desensite/handler/PhoneNumberDesensitizationHandler.java b/ballcat-common/ballcat-common-core/src/main/java/com/hccake/ballcat/common/core/desensite/handler/PhoneNumberDesensitizationHandler.java new file mode 100644 index 00000000..813bb2e3 --- /dev/null +++ b/ballcat-common/ballcat-common-core/src/main/java/com/hccake/ballcat/common/core/desensite/handler/PhoneNumberDesensitizationHandler.java @@ -0,0 +1,17 @@ +package com.hccake.ballcat.common.core.desensite.handler; + +import com.hccake.ballcat.common.core.desensite.DesensitizationTypeConstant; + +/** + * 【手机号】,某些国家手机号位数短,所以不做前三后四,使用前三后二 + * + * @author Hccake 2021/1/23 + * @version 1.0 + */ +public class PhoneNumberDesensitizationHandler extends AbstractCenterDesensitizationHandler { + + public PhoneNumberDesensitizationHandler() { + super(DesensitizationTypeConstant.PHONE_NUMBER, 3, 2); + } + +} diff --git a/ballcat-common/ballcat-common-core/src/main/resources/META-INF/services/com.hccake.ballcat.common.core.desensite.DesensitizationHandler b/ballcat-common/ballcat-common-core/src/main/resources/META-INF/services/com.hccake.ballcat.common.core.desensite.DesensitizationHandler new file mode 100644 index 00000000..7b207dc0 --- /dev/null +++ b/ballcat-common/ballcat-common-core/src/main/resources/META-INF/services/com.hccake.ballcat.common.core.desensite.DesensitizationHandler @@ -0,0 +1,7 @@ +com.hccake.ballcat.common.core.desensite.handler.AllMaskDesensitizationHandler +com.hccake.ballcat.common.core.desensite.handler.BankCardNODesensitizationHandler +com.hccake.ballcat.common.core.desensite.handler.EmailDesensitizationHandler +com.hccake.ballcat.common.core.desensite.handler.EncryptedPasswordDesensitizationHandler +com.hccake.ballcat.common.core.desensite.handler.FixedLengthDesensitizationHandler +com.hccake.ballcat.common.core.desensite.handler.IDCardNODesensitizationHandler +com.hccake.ballcat.common.core.desensite.handler.PhoneNumberDesensitizationHandler \ No newline at end of file