1.POM
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>jakarta.persistence</groupId>
<artifactId>jakarta.persistence-api</artifactId>
</dependency>
2.annotation
@Target
ElementType.FIELD 代表可用于属性
ElementType.METHOD 可用于方法
@Retention
RetentionPolicy.RUNTIME 运行时可用
@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
@JacksonAnnotationsInside
@JsonSerialize(using = DesensitizationJsonSerializer.class)
public @interface Desensitization {
Class<? extends AbstractDesensitization> value();
}
3.脱敏工具类
package com.mifan.common.core.utils;
import org.apache.commons.lang3.StringUtils;
/***
* @title DesensitizedUtils
* @description <TODO description class purpose>
* @author sfx
* @version 1.0.0
* @create 2022/9/26 14:04
**/
public class DesensitizedUtils {
/**
* 【中文姓名】两个字隐藏第二个字
* 单个字隐藏中间字
* 字符数字超过三个 后面的有隐藏
* 比如: 张* 王*五 欧阳娜*
*
* @param fullName
* @return
*/
public static String chineseName(String fullName) {
if (null == fullName || "".equals(fullName)) {
return fullName;
}
int len = fullName.length();
int pamaone = len / 2;
int pamatwo = pamaone - 1;
int pamathree = len % 3;
StringBuilder stringBuilder = new StringBuilder();
if (len <= 2) {
if (pamathree == 1) {
return "*";
}
stringBuilder.append(fullName.charAt(0));
stringBuilder.append("*");
} else {
if (pamatwo <= 0) {
stringBuilder.append(fullName.substring(0, 1));
stringBuilder.append("*");
stringBuilder.append(fullName.substring(len - 1, len));
}else {
stringBuilder.append(fullName.substring(0, 3));
for (int i = 0; i < len-3; i++) {
stringBuilder.append("*");
}
}
}
return stringBuilder.toString();
}
/**
* 【身份证号】显示最后四位,其他隐藏。共计18位或者15位,比如:*************1234
*
* @param id
* @return
*/
public static String idCardNum(String id) {
if (StringUtils.isBlank(id)) {
return "";
}
String num = StringUtils.right(id, 4);
return StringUtils.leftPad(num, StringUtils.length(id), "*");
}
/**
* 【固定电话 后四位,其他隐藏,比如1234
*
* @param num
* @return
*/
public static String fixedPhone(String num) {
if (StringUtils.isBlank(num)) {
return "";
}
return StringUtils.leftPad(StringUtils.right(num, 4), StringUtils.length(num), "*");
}
/**
* 【手机号码】前三位,后四位,其他隐藏,比如135****6810
*
* @param num
* @return
*/
public static String mobilePhone(String num) {
if (StringUtils.isBlank(num)) {
return "";
}
return StringUtils.left(num, 3).concat(StringUtils.removeStart(StringUtils.leftPad(StringUtils.right(num, 4), StringUtils.length(num), "*"), "***"));
}
/**
* 【地址】只显示到地区,不显示详细地址,比如:北京市海淀区****
*
* @param address
* @param sensitiveSize 敏感信息长度
* @return
*/
public static String address(String address, int sensitiveSize) {
if (StringUtils.isBlank(address)) {
return "";
}
int length = StringUtils.length(address);
return StringUtils.rightPad(StringUtils.left(address, length - sensitiveSize), length, "*");
}
/**
* 【电子邮箱 邮箱前缀仅显示第一个字母,前缀其他隐藏,用星号代替,@及后面的地址显示,比如:d**@126.com>
*
* @param email
* @return
*/
public static String email(String email) {
if (StringUtils.isBlank(email)) {
return "";
}
int index = StringUtils.indexOf(email, "@");
if (index <= 1)
return email;
else
return StringUtils.rightPad(StringUtils.left(email, 1), index, "*").concat(StringUtils.mid(email, index, StringUtils.length(email)));
}
/**
* 【银行卡号】前六位,后四位,其他用星号隐藏每位1个星号,比如:6222600**********1234>
*
* @param cardNum
* @return
*/
public static String bankCard(String cardNum) {
if (StringUtils.isBlank(cardNum)) {
return "";
}
return StringUtils.left(cardNum, 6).concat(StringUtils.removeStart(StringUtils.leftPad(StringUtils.right(cardNum, 4), StringUtils.length(cardNum), "*"), "******"));
}
/**
* 【密码】密码的全部字符都用*代替,比如:******
*
* @param password
* @return
*/
public static String password(String password) {
if (StringUtils.isBlank(password)) {
return "";
}
String pwd = StringUtils.left(password, 0);
return StringUtils.rightPad(pwd, StringUtils.length(password), "*");
}
}
4.
public abstract class AbstractDesensitization {
/**
* 脱敏
* @param value
* @return
*/
public abstract String serialize(String value);
}
4+.DesensitizationJsonSerializer
public class DesensitizationJsonSerializer extends JsonSerializer<String> implements ContextualSerializer {
private AbstractDesensitization desensitization;
public DesensitizationJsonSerializer() {
}
public DesensitizationJsonSerializer(AbstractDesensitization desensitization) {
this.desensitization = desensitization;
}
@Override
public void serialize(String s, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
jsonGenerator.writeString(desensitization.serialize(s));;
}
@Override
public JsonSerializer<?> createContextual(SerializerProvider serializerProvider, BeanProperty beanProperty) throws JsonMappingException {
JsonSerializer<?> jsonSerializer = null;
if(null == beanProperty) jsonSerializer = serializerProvider.findNullValueSerializer(beanProperty);
if(!Objects.equals(beanProperty.getType().getRawClass(), String.class))
jsonSerializer = serializerProvider.findValueSerializer(beanProperty.getType(), beanProperty);
if(Objects.equals(beanProperty.getType().getRawClass(), String.class)){
jsonSerializer = setDesensitization(jsonSerializer, beanProperty);
}
return jsonSerializer;
}
/**
* 设置脱敏
* @param beanProperty
* @return
*/
private JsonSerializer<?> setDesensitization(JsonSerializer<?> jsonSerializer, BeanProperty beanProperty) {
Desensitization desensitization = beanProperty.getAnnotation(Desensitization.class);
if (desensitization == null) desensitization = beanProperty.getContextAnnotation(Desensitization.class);
if (desensitization != null) {
//设置脱敏实例
try {
jsonSerializer = new DesensitizationJsonSerializer(desensitization.value().newInstance());
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
return jsonSerializer;
}
}
5.中文名脱敏,可拓展手机号等,只需继承AbstractDesensitization
/***
* @title ChineseNameDesensitization 中文名脱敏
* @description <TODO description class purpose>
* @author sfx
* @version 1.0.0
* @create 2022/9/26 15:55
**/
public class ChineseNameDesensitization extends AbstractDesensitization{
@Override
public String serialize(String value) {
return DesensitizedUtils.chineseName(value);
}
}
6.使用
public class user{
@Desensitization(ChineseNameDesensitization.class)
private String username;
}