Java实现数据脱敏案例

wen java案例 5

本文目录导读:

Java实现数据脱敏案例

  1. 脱敏工具类实现
  2. 基于注解的脱敏方案
  3. 脱敏处理器
  4. 实体类示例
  5. 实际应用示例
  6. 使用AOP实现自动脱敏
  7. 配置脱敏规则
  8. 测试类

我来为您提供一个完整的Java数据脱敏实现方案,包含多种脱敏策略和实际应用案例。

脱敏工具类实现

import java.util.regex.Pattern;
/**
 * 数据脱敏工具类
 */
public class DesensitizedUtil {
    /**
     * 手机号脱敏:保留前3位和后4位
     */
    public static String mobilePhone(String mobile) {
        if (isEmpty(mobile)) {
            return "";
        }
        return mobile.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2");
    }
    /**
     * 身份证号脱敏:保留前6位和后4位
     */
    public static String idCard(String idCard) {
        if (isEmpty(idCard)) {
            return "";
        }
        return idCard.replaceAll("(\\d{6})\\d{8}(\\d{4})", "$1********$2");
    }
    /**
     * 银行卡号脱敏:保留前4位和后4位
     */
    public static String bankCard(String cardNo) {
        if (isEmpty(cardNo)) {
            return "";
        }
        return cardNo.replaceAll("(\\d{4})\\d{8,12}(\\d{4})", "$1********$2");
    }
    /**
     * 姓名脱敏:保留姓氏,名字用*代替
     */
    public static String chineseName(String name) {
        if (isEmpty(name)) {
            return "";
        }
        if (name.length() == 1) {
            return "*";
        }
        return name.replaceAll("(.)(.*)", "$1" + repeat("*", name.length() - 1));
    }
    /**
     * 邮箱脱敏:保留第一个字母和@后面部分
     */
    public static String email(String email) {
        if (isEmpty(email)) {
            return "";
        }
        int index = email.indexOf("@");
        if (index <= 1) {
            return email;
        }
        return email.substring(0, 1) + "***" + email.substring(index);
    }
    /**
     * 地址脱敏:保留前6个字符
     */
    public static String address(String address) {
        if (isEmpty(address)) {
            return "";
        }
        if (address.length() <= 6) {
            return address;
        }
        return address.substring(0, 6) + "******";
    }
    /**
     * 密码脱敏:全部替换为*
     */
    public static String password(String password) {
        if (isEmpty(password)) {
            return "";
        }
        return repeat("*", password.length());
    }
    /**
     * 自定义脱敏
     */
    public static String custom(String str, int front, int end) {
        if (isEmpty(str)) {
            return "";
        }
        if (str.length() <= front + end) {
            return str;
        }
        return str.substring(0, front) + repeat("*", str.length() - front - end) + str.substring(str.length() - end);
    }
    private static boolean isEmpty(String str) {
        return str == null || str.trim().isEmpty();
    }
    private static String repeat(String str, int count) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < count; i++) {
            sb.append(str);
        }
        return sb.toString();
    }
}

基于注解的脱敏方案

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * 脱敏注解
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SensitiveField {
    SensitiveType type() default SensitiveType.CUSTOM;
    int front() default 2;  // 保留前几位
    int end() default 2;    // 保留后几位
}
/**
 * 脱敏类型枚举
 */
public enum SensitiveType {
    MOBILE_PHONE,  // 手机号
    ID_CARD,       // 身份证
    BANK_CARD,     // 银行卡
    NAME,          // 姓名
    EMAIL,         // 邮箱
    ADDRESS,       // 地址
    PASSWORD,      // 密码
    CUSTOM         // 自定义
}

脱敏处理器

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
/**
 * 脱敏处理器
 */
public class SensitiveDataProcessor {
    /**
     * 处理单个对象
     */
    public static <T> T process(T object) {
        if (object == null) {
            return null;
        }
        try {
            Class<?> clazz = object.getClass();
            Field[] fields = clazz.getDeclaredFields();
            for (Field field : fields) {
                if (field.isAnnotationPresent(SensitiveField.class)) {
                    field.setAccessible(true);
                    Object value = field.get(object);
                    if (value instanceof String) {
                        SensitiveField annotation = field.getAnnotation(SensitiveField.class);
                        String result = desensitize((String) value, annotation);
                        field.set(object, result);
                    }
                }
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return object;
    }
    /**
     * 处理对象列表
     */
    public static <T> List<T> processList(List<T> list) {
        if (list == null || list.isEmpty()) {
            return list;
        }
        List<T> result = new ArrayList<>();
        for (T item : list) {
            result.add(process(item));
        }
        return result;
    }
    /**
     * 执行脱敏
     */
    private static String desensitize(String value, SensitiveField annotation) {
        if (value == null || value.isEmpty()) {
            return value;
        }
        switch (annotation.type()) {
            case MOBILE_PHONE:
                return DesensitizedUtil.mobilePhone(value);
            case ID_CARD:
                return DesensitizedUtil.idCard(value);
            case BANK_CARD:
                return DesensitizedUtil.bankCard(value);
            case NAME:
                return DesensitizedUtil.chineseName(value);
            case EMAIL:
                return DesensitizedUtil.email(value);
            case ADDRESS:
                return DesensitizedUtil.address(value);
            case PASSWORD:
                return DesensitizedUtil.password(value);
            case CUSTOM:
                return DesensitizedUtil.custom(value, annotation.front(), annotation.end());
            default:
                return value;
        }
    }
}

实体类示例

/**
 * 用户实体类
 */
public class User {
    private Long id;
    @SensitiveField(type = SensitiveType.NAME)
    private String name;
    @SensitiveField(type = SensitiveType.MOBILE_PHONE)
    private String phone;
    @SensitiveField(type = SensitiveType.ID_CARD)
    private String idCard;
    @SensitiveField(type = SensitiveType.EMAIL)
    private String email;
    @SensitiveField(type = SensitiveType.PASSWORD)
    private String password;
    @SensitiveField(type = SensitiveType.ADDRESS)
    private String address;
    @SensitiveField(type = SensitiveType.BANK_CARD)
    private String bankCard;
    @SensitiveField(type = SensitiveType.CUSTOM, front = 2, end = 2)
    private String customField;
    // getters and setters
    // ...
}

实际应用示例

import com.alibaba.fastjson2.JSON;
import java.util.Arrays;
import java.util.List;
/**
 * 脱敏使用示例
 */
public class DesensitizationDemo {
    public static void main(String[] args) {
        // 创建测试数据
        User user = new User();
        user.setId(1L);
        user.setName("张三");
        user.setPhone("13812345678");
        user.setIdCard("110101199003071234");
        user.setEmail("zhangsan@example.com");
        user.setPassword("password123");
        user.setAddress("北京市海淀区中关村大街1号");
        user.setBankCard("6222020302012345678");
        user.setCustomField("自定义字段测试");
        // 单个对象脱敏
        System.out.println("=== 单个对象脱敏 ===");
        User processed = SensitiveDataProcessor.process(user);
        System.out.println(JSON.toJSONString(processed, true));
        // 列表脱敏
        System.out.println("=== 列表脱敏 ===");
        List<User> userList = Arrays.asList(user, user);
        List<User> processedList = SensitiveDataProcessor.processList(userList);
        System.out.println(JSON.toJSONString(processedList));
        // 直接使用工具类脱敏
        System.out.println("=== 工具类直接调用 ===");
        System.out.println("手机号: " + DesensitizedUtil.mobilePhone("13812345678"));
        System.out.println("身份证: " + DesensitizedUtil.idCard("110101199003071234"));
        System.out.println("姓名: " + DesensitizedUtil.chineseName("张三丰"));
        System.out.println("邮箱: " + DesensitizedUtil.email("zhangsan@example.com"));
        System.out.println("银行卡: " + DesensitizedUtil.bankCard("6222020302012345678"));
        System.out.println("地址: " + DesensitizedUtil.address("北京市海淀区中关村大街1号"));
        System.out.println("密码: " + DesensitizedUtil.password("123456"));
        System.out.println("自定义: " + DesensitizedUtil.custom("123456789", 2, 3));
    }
}

使用AOP实现自动脱敏

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
/**
 * 自动脱敏切面
 */
@Aspect
@Component
public class SensitiveDataAspect {
    /**
     * 拦截Controller层的返回结果进行脱敏
     */
    @Around("@annotation(com.example.annotation.NoSensitive) || within(com.example.controller.*)")
    public Object processData(ProceedingJoinPoint joinPoint) throws Throwable {
        Object result = joinPoint.proceed();
        if (result == null) {
            return null;
        }
        // 处理单个对象
        if (!(result instanceof Iterable) && !(result instanceof org.springframework.http.ResponseEntity)) {
            return SensitiveDataProcessor.process(result);
        }
        // 处理列表
        if (result instanceof List) {
            return SensitiveDataProcessor.processList((List<?>) result);
        }
        return result;
    }
}

配置脱敏规则

import java.util.HashMap;
import java.util.Map;
/**
 * 脱敏规则配置
 */
public class SensitiveRuleConfig {
    private static final Map<String, SensitiveType> RULE_MAP = new HashMap<>();
    static {
        RULE_MAP.put("userName", SensitiveType.NAME);
        RULE_MAP.put("mobile", SensitiveType.MOBILE_PHONE);
        RULE_MAP.put("idCard", SensitiveType.ID_CARD);
        RULE_MAP.put("email", SensitiveType.EMAIL);
        RULE_MAP.put("password", SensitiveType.PASSWORD);
        RULE_MAP.put("address", SensitiveType.ADDRESS);
        RULE_MAP.put("bankCard", SensitiveType.BANK_CARD);
    }
    /**
     * 根据字段名获取脱敏策略
     */
    public static SensitiveType getType(String fieldName) {
        return RULE_MAP.getOrDefault(fieldName, SensitiveType.CUSTOM);
    }
}
/**
 * 动态脱敏处理
 */
public class DynamicDesensitizedProcessor {
    /**
     * 处理Map类型的参数
     */
    public static Map<String, Object> processMap(Map<String, Object> data) {
        if (data == null || data.isEmpty()) {
            return data;
        }
        Map<String, Object> result = new HashMap<>();
        for (Map.Entry<String, Object> entry : data.entrySet()) {
            String key = entry.getKey();
            Object value = entry.getValue();
            if (value instanceof String) {
                SensitiveType type = SensitiveRuleConfig.getType(key);
                switch (type) {
                    case NAME:
                        result.put(key, DesensitizedUtil.chineseName((String) value));
                        break;
                    case MOBILE_PHONE:
                        result.put(key, DesensitizedUtil.mobilePhone((String) value));
                        break;
                    case ID_CARD:
                        result.put(key, DesensitizedUtil.idCard((String) value));
                        break;
                    case EMAIL:
                        result.put(key, DesensitizedUtil.email((String) value));
                        break;
                    case PASSWORD:
                        result.put(key, DesensitizedUtil.password((String) value));
                        break;
                    case ADDRESS:
                        result.put(key, DesensitizedUtil.address((String) value));
                        break;
                    case BANK_CARD:
                        result.put(key, DesensitizedUtil.bankCard((String) value));
                        break;
                    default:
                        result.put(key, value);
                }
            } else {
                result.put(key, value);
            }
        }
        return result;
    }
}

测试类

import java.util.HashMap;
import java.util.Map;
/**
 * 测试类
 */
public class DesensitizedTest {
    public static void main(String[] args) {
        // 测试各种脱敏情况
        System.out.println("=== 边界测试 ===");
        System.out.println("空字符串: '" + DesensitizedUtil.mobilePhone("") + "'");
        System.out.println("null值: '" + DesensitizedUtil.mobilePhone(null) + "'");
        System.out.println("短字符串: " + DesensitizedUtil.chineseName("刘"));
        System.out.println("英文名: " + DesensitizedUtil.chineseName("John"));
        // 测试Map处理
        System.out.println("=== Map数据脱敏 ===");
        Map<String, Object> userData = new HashMap<>();
        userData.put("userName", "张三");
        userData.put("mobile", "13812345678");
        userData.put("idCard", "110101199003071234");
        userData.put("email", "zhangsan@example.com");
        userData.put("password", "abc123");
        Map<String, Object> processedData = DynamicDesensitizedProcessor.processMap(userData);
        processedData.forEach((key, value) -> System.out.println(key + ": " + value));
    }
}

这个案例提供了完整的Java数据脱敏解决方案,包括:

  1. 多种脱敏策略:手机号、身份证、银行卡、姓名、邮箱、地址、密码等
  2. 注解方式:通过@SensitiveField注解实现字段级脱敏
  3. 自动处理:使用AOP实现返回值自动脱敏
  4. 动态配置:支持配置化的脱敏规则
  5. 实用工具:提供独立的工具类方法供直接调用

使用方式灵活,可以根据实际需求选择适合的脱敏方式。

抱歉,评论功能暂时关闭!