提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
提示:这里可以添加本文要记录的大概内容:
由于项目加入了IAST的检测,检出了接口敏感数据的漏洞,所以需要去修复,刚开始是准备在dao层借助Mybatis-Plus 的 TypeHandler 写的 ,结果写了之后发现数据取出来之后,后续的逻辑可能会使用到 去除的数据,最后也是放弃了这个方式,使用了自定义的注解方式处理,故整理了一个注解方式脱敏数据的方法,作为日志记录
提示:以下是本篇文章正文内容,下面案例可供参考
一、代码
Desensitize
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(value = ElementType.FIELD)
public @interface Desensitize {
DesensitizeType type() default DesensitizeType.CUSTOM;
String customPattern() default "";
String replacement() default "*";
}
public enum DesensitizeType {
PHONE,
EMAIL,
CREDIT_CARD,
ID_CARD,
NAME,
CUSTOM
}
DesensitizeProcessor
import java.lang.reflect.Field;
import java.util.List;
public class DesensitizeProcessor {
public static <T> List<T> process(List<T> dataList) {
if (dataList == null || dataList.isEmpty()) {
return dataList;
}
for (T data : dataList) {
processSingle(data);
}
return dataList;
}
private static <T> void processSingle(T data) {
if (data == null) {
return;
}
Class<?> clazz = data.getClass();
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
if (field.isAnnotationPresent(Desensitize.class)) {
Desensitize annotation = field.getAnnotation(Desensitize.class);
DesensitizeType type = annotation.type();
String customPattern = annotation.customPattern();
String replacement = annotation.replacement();
field.setAccessible(true);
try {
Object value = field.get(data);
if (value instanceof String) {
String desensitizedValue = DesensitizeUtil.desensitize((String) value, type,customPattern,replacement);
field.set(data, desensitizedValue);
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
}
DesensitizeUtil
public class DesensitizeUtil {
public static String desensitize(String data, DesensitizeType type,String customPattern,String replacement){
if (data == null || data.isEmpty()) return data;
if (type == DesensitizeType.CUSTOM && !customPattern.isEmpty()){
return data.replaceAll(customPattern,replacement);
}
switch (type) {
case PHONE:
return data.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2");
case EMAIL:
return data.replaceAll("(\\w{1})[^@]*(@.*)", "$1****$2");
case ID_CARD:
return data.replaceAll("(\\d{6})\\d{8}(\\d{4})", "$1********$2");
case NAME:
return data.length() == 2 ? data.charAt(0) + "*" : data.charAt(0) + "**";
case CREDIT_CARD:
return data.replaceAll("(\\d{6})\\d{8}(\\d{6})", "$1********$2");
default:
return data;
}
}
}
User
public class User {
@Desensitize(type = DesensitizeType.PHONE)
private String phone;
@Desensitize(type = DesensitizeType.EMAIL)
private String email;
@Desensitize(type = DesensitizeType.NAME)
private String name;
@Desensitize(type = DesensitizeType.CREDIT_CARD)
private String creditCode;
@Desensitize(type = DesensitizeType.ID_CARD)
private String idCard;
@Desensitize(type = DesensitizeType.CUSTOM, customPattern = "(\\d{4})\\d{4}(\\d{4})",replacement = "$1****$2")
private String customCode;
public String getCustomCode() {
return customCode;
}
public void setCustomCode(String customCode) {
this.customCode = customCode;
}
public String getIdCard() {
return idCard;
}
public void setIdCard(String idCard) {
this.idCard = idCard;
}
public String getCreditCode() {
return creditCode;
}
public void setCreditCode(String creditCode) {
this.creditCode = creditCode;
}
// Getters and Setters
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Test
import java.util.ArrayList;
import java.util.List;
public class Test {
public static void main(String[] args) {
List<User> users = new ArrayList<>();
User user1 = new User();
user1.setPhone("13812345678");
user1.setEmail("test@example.com");
user1.setName("张三");
user1.setIdCard("412702199807058116");
user1.setCreditCode("23478923467238434567");
user1.setCustomCode("423638937847");
User user2 = new User();
user2.setPhone("13987654321");
user2.setEmail("example@domain.com");
user2.setName("李四");
user2.setIdCard("413702199807058117");
user2.setCreditCode("23478324324728434567");
user2.setCustomCode("039273877847");
users.add(user1);
users.add(user2);
// 脱敏处理
DesensitizeProcessor.process(users);
// 打印结果
users.forEach(user -> {
System.out.println("Phone: " + user.getPhone());
System.out.println("Email: " + user.getEmail());
System.out.println("Name: " + user.getName());
System.out.println("IdCard: " + user.getIdCard());
System.out.println("CreditCode: " + user.getCreditCode());
System.out.println("CustomCode: " + user.getCustomCode());
});
}
}
问题思考
如果使用Mybatis-Plus的TypeHandler (字段类型处理器)的话,如果开启mybatis缓存的话,第二次查询的的值是脱敏的数据还是原来的数据?