本文目录导读:

我来为您提供一个完整的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数据脱敏解决方案,包括:
- 多种脱敏策略:手机号、身份证、银行卡、姓名、邮箱、地址、密码等
- 注解方式:通过
@SensitiveField注解实现字段级脱敏 - 自动处理:使用AOP实现返回值自动脱敏
- 动态配置:支持配置化的脱敏规则
- 实用工具:提供独立的工具类方法供直接调用
使用方式灵活,可以根据实际需求选择适合的脱敏方式。