新增脱敏工具,支持SPI形式追加用户自定义脱敏处理器

This commit is contained in:
b2baccline
2021-01-23 01:21:56 +08:00
parent 7931559bc7
commit 6efa588610
15 changed files with 426 additions and 0 deletions

View File

@@ -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);
}

View File

@@ -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<String, DesensitizationHandler> TYPE_MAPS = new ConcurrentHashMap<>();
static {
// SPI 加载所有的脱敏类型处理
ServiceLoader<DesensitizationHandler> loadedDrivers = ServiceLoader.load(DesensitizationHandler.class);
for (DesensitizationHandler desensitizationHandler : loadedDrivers) {
TYPE_MAPS.put(desensitizationHandler.getType(), desensitizationHandler);
}
}
}

View File

@@ -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";
}

View File

@@ -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();
}

View File

@@ -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<String> 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);
}
}

View File

@@ -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();
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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");
}
}

View File

@@ -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);
}
}

View File

@@ -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 "******";
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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