✨ 新增脱敏工具,支持SPI形式追加用户自定义脱敏处理器
This commit is contained in:
@@ -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);
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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";
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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 "******";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user