本文目录导读:

我将为您提供一个完整的Java数据脱敏案例,涵盖常见的脱敏场景和实现方案。
核心脱敏工具类
import java.util.regex.Pattern;
/**
* 数据脱敏工具类
*/
public class DataMaskingUtil {
/**
* 姓名脱敏(保留姓,名用*代替)
* 张三 -> 张*
* 张三丰 -> 张*丰
*/
public static String maskName(String name) {
if (name == null || name.isEmpty()) {
return name;
}
if (name.length() == 1) {
return "*";
}
if (name.length() == 2) {
return name.charAt(0) + "*";
}
// 保留第一个和最后一个字符
return name.charAt(0) +
"*".repeat(name.length() - 2) +
name.charAt(name.length() - 1);
}
/**
* 手机号脱敏(保留前3后4)
* 13812345678 -> 138****5678
*/
public static String maskMobile(String mobile) {
if (mobile == null || mobile.length() != 11) {
return mobile;
}
return mobile.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2");
}
/**
* 身份证号脱敏(保留前4后4)
* 110101199001011234 -> 1101**********1234
*/
public static String maskIdCard(String idCard) {
if (idCard == null || idCard.length() < 8) {
return idCard;
}
return idCard.replaceAll("(\\d{4})\\d{10}(\\d{4})", "$1**********$2");
}
/**
* 银行卡号脱敏(保留前4后4)
* 6222021234567890123 -> 6222************123
*/
public static String maskBankCard(String cardNo) {
if (cardNo == null || cardNo.length() < 8) {
return cardNo;
}
return cardNo.replaceAll("(\\d{4})\\d{10,}(\\d{4})", "$1****$2");
}
/**
* 邮箱脱敏(保留前缀前2和后缀域名)
* zhangsan@example.com -> zh***@example.com
*/
public static String maskEmail(String email) {
if (email == null || email.isEmpty()) {
return email;
}
int atIndex = email.indexOf('@');
if (atIndex <= 0) {
return email;
}
String prefix = email.substring(0, atIndex);
String suffix = email.substring(atIndex);
if (prefix.length() <= 2) {
return "***" + suffix;
}
return prefix.substring(0, 2) +
"***" +
suffix;
}
/**
* 地址脱敏(保留前几个字符)
* 北京市朝阳区xx街道xx小区 -> 北京市朝阳区***
*/
public static String maskAddress(String address) {
if (address == null || address.isEmpty()) {
return address;
}
if (address.length() <= 6) {
return "***";
}
return address.substring(0, 6) + "***";
}
/**
* IP地址脱敏
* 192.168.1.100 -> 192.168.*.*
*/
public static String maskIp(String ip) {
if (ip == null || ip.isEmpty()) {
return ip;
}
String[] parts = ip.split("\\.");
if (parts.length != 4) {
return ip;
}
return parts[0] + "." + parts[1] + ".*.*";
}
/**
* 密码脱敏
* 123456 -> ******
*/
public static String maskPassword(String password) {
if (password == null || password.isEmpty()) {
return password;
}
return "*".repeat(password.length());
}
}
注解定义
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 MaskField {
/**
* 脱敏类型
*/
MaskType type() default MaskType.DEFAULT;
/**
* 自定义脱敏正则表达式(当type为CUSTOM时使用)
*/
String regex() default "";
/**
* 脱敏替换字符串
*/
String replacement() default "***";
/**
* 是否脱敏
*/
boolean enabled() default true;
/**
* 脱敏类型枚举
*/
enum MaskType {
DEFAULT, // 默认不脱敏
NAME, // 姓名
MOBILE, // 手机号
ID_CARD, // 身份证号
BANK_CARD, // 银行卡号
EMAIL, // 邮箱
ADDRESS, // 地址
IP, // IP地址
PASSWORD, // 密码
CUSTOM // 自定义
}
}
脱敏处理器
import java.lang.reflect.Field;
import java.util.Collection;
import java.util.Map;
/**
* 数据脱敏处理器
*/
public class DataMaskingProcessor {
/**
* 处理脱敏(通用方法)
* @param object 需要脱敏的对象
* @return 脱敏后的对象
*/
public static <T> T mask(T object) {
if (object == null) {
return null;
}
processObject(object);
return object;
}
/**
* 处理集合
*/
public static <T> Collection<T> maskCollection(Collection<T> collection) {
if (collection == null || collection.isEmpty()) {
return collection;
}
for (T item : collection) {
mask(item);
}
return collection;
}
/**
* 递归处理对象
*/
private static void processObject(Object object) {
if (object == null) {
return;
}
// 处理基本类型和包装类
if (isBasicType(object) || object instanceof String) {
return;
}
// 处理Collection
if (object instanceof Collection) {
for (Object item : (Collection<?>) object) {
processObject(item);
}
return;
}
// 处理Map
if (object instanceof Map) {
for (Object value : ((Map<?, ?>) object).values()) {
processObject(value);
}
return;
}
// 处理数组
if (object.getClass().isArray()) {
Object[] array = (Object[]) object;
for (Object item : array) {
processObject(item);
}
return;
}
// 处理普通对象
Class<?> clazz = object.getClass();
// 跳过JDK类
if (clazz.getName().startsWith("java.") || clazz.getName().startsWith("javax.")) {
return;
}
// 获取所有字段(包括父类)
while (clazz != null && clazz != Object.class) {
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
processField(field, object);
}
clazz = clazz.getSuperclass();
}
}
/**
* 处理字段
*/
private static void processField(Field field, Object object) {
try {
// 检查是否有脱敏注解
if (field.isAnnotationPresent(MaskField.class)) {
MaskField maskField = field.getAnnotation(MaskField.class);
if (!maskField.enabled()) {
return;
}
field.setAccessible(true);
Object value = field.get(object);
// 处理字符串类型字段
if (value instanceof String) {
String maskedValue = maskValue((String) value, maskField);
field.set(object, maskedValue);
}
// 处理其他类型字段
else if (value != null) {
processObject(value);
}
}
// 没有注解但字段类型需要处理的
else {
field.setAccessible(true);
Object value = field.get(object);
if (value != null && !isBasicType(value)) {
processObject(value);
}
}
} catch (IllegalAccessException e) {
// 忽略访问权限异常
}
}
/**
* 根据注解配置执行脱敏
*/
private static String maskValue(String value, MaskField maskField) {
if (value == null || value.isEmpty()) {
return value;
}
switch (maskField.type()) {
case NAME:
return DataMaskingUtil.maskName(value);
case MOBILE:
return DataMaskingUtil.maskMobile(value);
case ID_CARD:
return DataMaskingUtil.maskIdCard(value);
case BANK_CARD:
return DataMaskingUtil.maskBankCard(value);
case EMAIL:
return DataMaskingUtil.maskEmail(value);
case ADDRESS:
return DataMaskingUtil.maskAddress(value);
case IP:
return DataMaskingUtil.maskIp(value);
case PASSWORD:
return DataMaskingUtil.maskPassword(value);
case CUSTOM:
return maskCustom(value, maskField);
default:
return value;
}
}
/**
* 自定义脱敏
*/
private static String maskCustom(String value, MaskField maskField) {
String regex = maskField.regex();
String replacement = maskField.replacement();
if (regex != null && !regex.isEmpty()) {
return value.replaceAll(regex, replacement);
}
return value.substring(0, Math.min(2, value.length())) +
"*".repeat(Math.max(0, value.length() - 2));
}
/**
* 判断是否为基本类型
*/
private static boolean isBasicType(Object object) {
return object instanceof Number ||
object instanceof Boolean ||
object instanceof Character ||
object instanceof Byte;
}
}
实体类示例
import lombok.Data;
/**
* 用户实体类
*/
@Data
public class User {
private Long id;
@MaskField(type = MaskField.MaskType.NAME)
private String name;
@MaskField(type = MaskField.MaskType.MOBILE)
private String mobile;
@MaskField(type = MaskField.MaskType.ID_CARD)
private String idCard;
@MaskField(type = MaskField.MaskType.EMAIL)
private String email;
@MaskField(type = MaskField.MaskType.ADDRESS)
private String address;
@MaskField(type = MaskField.MaskType.PASSWORD)
private String password;
@MaskField(type = MaskField.MaskType.IP)
private String lastLoginIp;
private Integer age;
}
应用示例
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* 使用示例
*/
public class MaskingExample {
public static void main(String[] args) {
// 单个对象脱敏
User user = new User();
user.setId(1L);
user.setName("张三丰");
user.setMobile("13812345678");
user.setIdCard("110101199001011234");
user.setEmail("zhangsan@example.com");
user.setAddress("北京市朝阳区某某街道某某小区");
user.setPassword("123456abc");
user.setLastLoginIp("192.168.1.100");
user.setAge(30);
System.out.println("=== 原始数据 ===");
printUser(user);
// 执行脱敏
DataMaskingProcessor.mask(user);
System.out.println("\n=== 脱敏后数据 ===");
printUser(user);
// 集合脱敏
System.out.println("\n=== 集合脱敏示例 ===");
List<User> users = Arrays.asList(user);
DataMaskingProcessor.maskCollection(users);
// 直接调用工具类
System.out.println("\n=== 直接调用工具类 ===");
System.out.println("姓名: " + DataMaskingUtil.maskName("张三丰"));
System.out.println("手机号: " + DataMaskingUtil.maskMobile("13812345678"));
System.out.println("身份证: " + DataMaskingUtil.maskIdCard("110101199001011234"));
System.out.println("邮箱: " + DataMaskingUtil.maskEmail("zhangsan@example.com"));
System.out.println("地址: " + DataMaskingUtil.maskAddress("北京市朝阳区某某街道某某小区"));
}
private static void printUser(User user) {
System.out.println("ID: " + user.getId());
System.out.println("姓名: " + user.getName());
System.out.println("手机号: " + user.getMobile());
System.out.println("身份证: " + user.getIdCard());
System.out.println("邮箱: " + user.getEmail());
System.out.println("地址: " + user.getAddress());
System.out.println("密码: " + user.getPassword());
System.out.println("IP: " + user.getLastLoginIp());
System.out.println("年龄: " + user.getAge());
}
}
配合Jackson序列化
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import java.io.IOException;
/**
* Jackson脱敏序列化器
*/
public class MaskingSerializer extends JsonSerializer<String> {
@Override
public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
if (value != null) {
gen.writeString(DataMaskingUtil.maskMobile(value));
}
}
}
/**
* 使用Jackson注解的实体类
*/
public class UserWithJackson {
private Long id;
// 使用Jackson注解实现脱敏
@JsonSerialize(using = MaskingSerializer.class)
private String mobile;
private String name;
// getters and setters
}
配置中心方案
import java.util.HashMap;
import java.util.Map;
/**
* 脱敏配置管理
*/
public class MaskingConfigManager {
private static final Map<String, Boolean> ENABLED_MASKING = new HashMap<>();
/**
* 初始化默认配置
*/
static {
// 默认启用手机号、身份证、密码脱敏
ENABLED_MASKING.put(MaskField.MaskType.MOBILE.name(), true);
ENABLED_MASKING.put(MaskField.MaskType.ID_CARD.name(), true);
ENABLED_MASKING.put(MaskField.MaskType.PASSWORD.name(), true);
}
/**
* 更新配置
*/
public static void updateConfig(String maskType, boolean enabled) {
ENABLED_MASKING.put(maskType, enabled);
}
/**
* 检查是否启用
*/
public static boolean isEnabled(MaskField.MaskType maskType) {
return ENABLED_MASKING.getOrDefault(maskType.name(), false);
}
}
这个完整的数据脱敏方案具有以下特点:
- 支持多种脱敏类型:姓名、手机号、身份证、银行卡、邮箱、地址、IP、密码等
- 注解驱动:通过注解配置需要脱敏的字段
- 自动处理嵌套对象:支持对象嵌套、集合、Map等复杂结构
- 可扩展性:支持自定义脱敏规则
- 性能优化:只处理带有注解的字段
- 与主流框架集成:支持Jackson等序列化框架
使用时只需在实体类字段上添加@MaskField注解,调用DataMaskingProcessor.mask()方法即可完成脱敏。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播