版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/a1053765496/article/details/120483598
import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
@JsonSerialize(using = SensitiveSerializer.class)
public @interface Sensitive {
int prefix() default 3;
int suffix() default 4;
String maskChar() default "*";
SensitiveEnum type() default SensitiveEnum.NONE;
}
import lombok.AllArgsConstructor;
import lombok.Getter;
@Getter
@AllArgsConstructor
public enum SensitiveEnum {
CHINESE_NAME(0, 1),
CHINESE_NAME2(-1, 0),
PHONE(3, 4),
BANK_CARD(2, 2),
ID_CARD(2, 4),
EMAIL(1, 0),
;
public final int prefixLength;
public final int suffixLength;
}
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 lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;
import java.io.IOException;
import java.util.List;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@NoArgsConstructor
@AllArgsConstructor
public class SensitiveSerializer extends JsonSerializer implements ContextualSerializer {
private int prefixLength;
private int suffixLength;
private String maskChar;
private SensitiveEnum sensitiveEnum;
public final static String template = "(?<=\w{%s})\w(?=\w{%s})";
@Override
public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
if (Objects.nonNull(value)) {
if (value instanceof String[]) {
String[] arr = (String[]) value;
gen.writeStartArray();
for (String s : arr) {
gen.writeString(s.trim().replaceAll(String.format(template, prefixLength, suffixLength), maskChar));
}
gen.writeEndArray();
}
if (value instanceof List) {
List> list = (List>) value;
if (!CollectionUtils.isEmpty(list) && list.get(0).getClass().equals(String.class)) {
gen.writeStartArray();
for (Object o : list) {
gen.writeString(((String) o).trim().replaceAll(String.format(template, prefixLength, suffixLength), maskChar));
}
gen.writeEndArray();
}
}
if (value instanceof String) {
String val = value.toString();
if (sensitiveEnum.equals(SensitiveEnum.CHINESE_NAME) || sensitiveEnum.equals(SensitiveEnum.CHINESE_NAME2)) {
if (checkCountName(val)) {
if (prefixLength == -1) {
gen.writeString(StringUtils.leftPad(StringUtils.right(val, val.length() - 1), val.length(), maskChar));
} else {
String left = StringUtils.left(val, prefixLength);
gen.writeString(StringUtils.rightPad(left, val.length() - suffixLength, maskChar).concat(StringUtils.right(val, suffixLength)));
}
} else {
gen.writeString(((String) value).trim().replaceAll(String.format(template, prefixLength, suffixLength), maskChar));
}
} else {
if (checkEmail(val)) {
gen.writeString(email(val, prefixLength, maskChar));
} else {
gen.writeString(((String) value).trim().replaceAll(String.format(template, prefixLength, suffixLength), maskChar));
}
}
}
}
}
@Override
public JsonSerializer> createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException {
if (Objects.nonNull(property)) {
Sensitive mask = property.getAnnotation(Sensitive.class);
if (Objects.isNull(mask)) {
mask = property.getContextAnnotation(Sensitive.class);
}
//可以改造成初始化regex正则表达式
if (mask.type().equals(SensitiveEnum.NONE)) {
return new SensitiveSerializer(mask.prefix(), mask.suffix(), mask.maskChar(), mask.type());
} else {
return new SensitiveSerializer(mask.type().prefixLength, mask.type().suffixLength, mask.maskChar(), mask.type());
}
} else {
return prov.findNullValueSerializer(null);
}
}
@Override
public Class handledType() {
return Object.class;
}
private boolean checkCountName(String countName) {
Pattern p = Pattern.compile("[u4e00-u9fa5]");
Matcher m = p.matcher(countName);
return m.find();
}
private boolean checkEmail(String email) {
Pattern patten = Pattern.compile("[\w]+@([\w]+.)+[\w]+");
Matcher matcher = patten.matcher(email);
return matcher.matches();
}
public static String email(String email, int prefixLength, String maskChar) {
if (StringUtils.isBlank(email)) {
return "";
}
int index = StringUtils.indexOf(email, "@");
if (index <= prefixLength) {
return email;
} else {
return StringUtils.rightPad(StringUtils.left(email, prefixLength), index, maskChar).concat(StringUtils.mid(email, index, StringUtils.length(email)));
}
}
}
使用如下:
@Data
public class SysUser {
@Sensitive(type = SensitiveEnum.PHONE)
private String mobile;
}
效果如下: