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

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


前言

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

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

WebAPI接口文档漏洞的防御是非常重要的,以下是一些常见的防御方法: 1. 鉴权和权限管理:确保只有经过授权的用户可以访问接口,并根据用户角色和权限限制他们的操作。使用基于令牌的身份验证机制,如OAuth,可以提供一定程度的安全性。 2. 输入验证和过滤:对于接口的输入参数进行验证和过滤,防止恶意用户提交非法或恶意数据。使用正则表达式、白名单过滤等技术可以有效地防止注入攻击、跨站脚本攻击等。 3. 输入参数编码:对于接口的输入参数,进行适当的编码处理,防止特殊字符的注入。例如,将HTML标签进行转义,以防止XSS攻击。 4. 错误处理和异常管理:合理处理和报告接口的错误和异常情况,避免泄露敏感信息。对于错误信息,可以根据用户角色进行脱敏处理,只返回必要的错误提示信息。 5. 日志记录和监控:及时记录接口的访问日志和异常情况,并建立监控机制,及时发现异常行为和攻击尝试。通过分析日志和监控数据,可以及时发现潜在的漏洞和安全风险。 6. 安全审计和漏洞扫描:定期进行安全审计和漏洞扫描,发现和修复潜在的漏洞。可以使用工具和服务来扫描接口的安全性,例如OWASP ZAP、Nessus等。 7. 安全意识培训:加强开发团队对接口安全的意识培训,教育开发人员遵循安全最佳实践,避免常见的安全漏洞。 总之,WebAPI接口文档漏洞的防御需要综合考虑技术、管理和人员培训等多个方面,保障接口的安全性和可靠性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值