【数据脱敏】接口敏感数据的漏洞修复

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

提示:这里可以添加本文要记录的大概内容:

由于项目加入了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缓存的话,第二次查询的的值是脱敏的数据还是原来的数据?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值