前言:
实现log脱敏 也可以实现注解脱敏!
1.注解
import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @program: sxsoft_expert
* @ClassName DataMasking
* @description: 数据脱敏自定义注解
* @author: 小帅哥
* @create: 2023-11-10 09:00
* @Version 1.0
**/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
public @interface DataMasking {
/**
* 数据脱敏类型
*/
DataMaskingType type() default DataMaskingType.CUSTOM;
/**
* 脱敏开始位置(包含)
*/
int start() default 0;
/**
* 脱敏结束位置(不包含)
*/
int end() default 0;
}
2.log脱敏循环coutroller调DataMaskFor 注解脱敏coutroller调DataMask方法
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.DesensitizedUtil;
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 org.apache.commons.lang.ArrayUtils;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.Objects;
/**
* @program: sxsoft_expert
* @ClassName DataMaskingSerialize
* @description: 自定义序列化类
* @author: 小帅哥
* @create: 2023-11-10 09:00
* @Version 1.0
**/
public class DataMaskingSerialize implements ContextualSerializer {
private static Integer start;
private static Integer end;
public static TestEntity DataMaskFor(TestEntity entity){
TestEntity obj = TestEntity.builder()
.userId(entity.getUserId())
.userName(entity.getUserName())
.password(entity.getPassword())
.address(entity.getAddress())
.email(entity.getEmail())
.fixedPhone(entity.getFixedPhone())
.mobilePhone(entity.getMobilePhone())
.carLicense(entity.getCarLicense())
.bankCard(entity.getBankCard())
.idCard(entity.getIdCard())
.custom(entity.getCustom())
.noMask(entity.getNoMask())
.build();
Field[] declaredFields = obj.getClass().getDeclaredFields();
Arrays.asList(declaredFields).stream().forEach(fielfd -> {
if(!ArrayUtils.isEmpty(fielfd.getAnnotations())){
// fielfd.set(obj, o);
DataMasking annotation = (DataMasking)fielfd.getAnnotations()[0];
DataMaskingType type = annotation.type();
try {
if(!fielfd.isAccessible()){
fielfd.setAccessible(true);
}
Object o = DataMask(fielfd.get(obj), type);
Class<?> type1 = fielfd.getType();
if(type1.isAssignableFrom(Integer.class)){
fielfd.set(obj, Integer.valueOf(o.toString()));
}
else if(type1.isAssignableFrom(String.class) && Objects.nonNull(o)){
fielfd.set(obj, o.toString());
}else{
fielfd.set(obj, o);
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
return obj;
}
public static Object DataMask(Object o ,DataMaskingType type) throws IOException {
Object obj = null;
String value = String.valueOf(o);
switch (type) {
//userId
case USER_ID:
obj = String.valueOf(DesensitizedUtil.desensitized(value, DesensitizedUtil.DesensitizedType.USER_ID));
break;
//中文名
case CHINESE_NAME:
obj = (DesensitizedUtil.desensitized(value, DesensitizedUtil.DesensitizedType.CHINESE_NAME));
break;
//身份证号
case ID_CARD:
obj = (DesensitizedUtil.desensitized(value, DesensitizedUtil.DesensitizedType.ID_CARD));
break;
//座机
case FIXED_PHONE:
obj = (DesensitizedUtil.desensitized(value, DesensitizedUtil.DesensitizedType.FIXED_PHONE));
break;
//手机号
case MOBILE_PHONE:
obj = (DesensitizedUtil.desensitized(value, DesensitizedUtil.DesensitizedType.MOBILE_PHONE));
break;
//地址
case ADDRESS:
obj = (DesensitizedUtil.desensitized(value, DesensitizedUtil.DesensitizedType.ADDRESS));
break;
//邮箱
case EMAIL:
obj = (DesensitizedUtil.desensitized(value, DesensitizedUtil.DesensitizedType.EMAIL));
break;
case BANK_CARD:
obj = (DesensitizedUtil.desensitized(value, DesensitizedUtil.DesensitizedType.BANK_CARD));
break;
//密码
case PASSWORD:
obj = (DesensitizedUtil.desensitized(value, DesensitizedUtil.DesensitizedType.PASSWORD));
break;
//中国大陆车牌号
case CAR_LICENSE:
obj = (DesensitizedUtil.desensitized(value, DesensitizedUtil.DesensitizedType.CAR_LICENSE));
break;
// case IPV4:
// obj = (DesensitizedUtil.desensitized(value, DesensitizedUtil.DesensitizedType.IPV4));
// break;
// case IPV6:
// obj = (DesensitizedUtil.desensitized(value, DesensitizedUtil.DesensitizedType.IPV6));
// break;
//自定义
case CUSTOM:
obj = CharSequenceUtil.hide(value, 3,5);
break;
default:
break;
}
return obj;
}
@Override
public JsonSerializer<?> createContextual(SerializerProvider serializerProvider, BeanProperty beanProperty) throws JsonMappingException {
if (Objects.nonNull(beanProperty)) {
//判断是否为string类型
if (Objects.equals(beanProperty.getType().getRawClass(), String.class)) {
DataMasking anno = beanProperty.getAnnotation(DataMasking.class);
if (Objects.isNull(anno)) {
anno = beanProperty.getContextAnnotation(DataMasking.class);
}
if (Objects.nonNull(anno)) {
// return new DataMaskingSerialize(anno.type());
}
}
return serializerProvider.findValueSerializer(beanProperty.getType(), beanProperty);
}
return serializerProvider.findNullValueSerializer(null);
}
}
3.枚举 脱敏类型
/**
* @program: sxsoft_expert
* @ClassName DataMaskingType
* @description:脱敏枚举
* @author: 小帅哥
* @create: 2023-11-10 09:00
* @Version 1.0
**/
public enum DataMaskingType {
/**
* 用户ID
*/
USER_ID,
/**
* 中文名
*/
CHINESE_NAME,
/**
* 身份证号
*/
ID_CARD,
/**
* 座机
*/
FIXED_PHONE,
/**
* 手机号
*/
MOBILE_PHONE,
/**
* 地址
*/
ADDRESS,
/**
* 邮箱
*/
EMAIL,
/**
* 密码
*/
PASSWORD,
/**
* 中国大陆车牌号
*/
CAR_LICENSE,
/**
* 银行卡号
*/
BANK_CARD,
/**
* IPv4地址
*/
IPV4,
/**
* IPv6地址
*/
IPV6,
/**
* 自定义类型
*/
CUSTOM;
}
4.类
import lombok.*;
/**
* @program: sxsoft_expert
* @ClassName TestEntity
* @description:
* @author: 小帅哥
* @create: 2023-11-10 09:00
* @Version 1.0
**/
@Data
@Builder
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class TestEntity {
@DataMasking(type = DataMaskingType.USER_ID)
private Integer userId;
@DataMasking(type = DataMaskingType.CHINESE_NAME)
private String userName;
@DataMasking(type = DataMaskingType.ADDRESS)
private String address;
@DataMasking(type = DataMaskingType.ID_CARD)
private String idCard;
@DataMasking(type = DataMaskingType.FIXED_PHONE)
private String fixedPhone;
@DataMasking(type = DataMaskingType.MOBILE_PHONE)
private String mobilePhone;
@DataMasking(type = DataMaskingType.EMAIL)
private String email;
@DataMasking(type = DataMaskingType.PASSWORD)
private String password;
@DataMasking(type = DataMaskingType.CAR_LICENSE)
private String carLicense;
@DataMasking(type = DataMaskingType.BANK_CARD)
private String bankCard;
// @DataMasking(type = DataMaskingType.IPV4)
// private String ipv4;
//
// @DataMasking(type = DataMaskingType.IPV6)
// private String ipv6;
@DataMasking(type = DataMaskingType.CUSTOM,start = 3,end = 9)
private String custom;
/**
* 不进行数据脱敏的字段
*/
private String noMask;
}
5.coutroller(log脱敏循环coutroller调DataMaskFor 注解脱敏coutroller调DataMask方法)
import com.example.demo11.service.impl.TestServiceImpl;
import com.example.demo11.uilt.TestEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class Coutroller {
@Autowired
private TestServiceImpl testService;
@RequestMapping(value="/test")
public TestEntity test() {
//只能直接返回实体?
TestEntity entity ;
entity = testService.tt();
return entity;
}
}
完全可以实现log脱敏!