Java 敏感数据脱敏:自定义注解与 AOP 实现
·
Java 敏感数据脱敏:自定义注解与 AOP 实现
1. 核心概念
- 敏感数据脱敏:将敏感信息(如手机号、身份证号)转换为部分隐藏的非敏感形式
- 自定义注解:标记需要脱敏的字段或方法
- AOP(面向切面编程):在方法执行前后插入脱敏逻辑
2. 实现步骤
2.1 定义脱敏策略枚举
public enum SensitiveStrategy {
PHONE, // 手机号脱敏:138****1234
ID_CARD, // 身份证脱敏:110***********123X
NAME, // 姓名脱敏:张*三
DEFAULT // 默认脱敏:保留首尾字符
}
2.2 创建自定义注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Sensitive {
SensitiveStrategy strategy();
}
2.3 实现脱敏工具类
public class SensitiveUtil {
public static String desensitize(String value, SensitiveStrategy strategy) {
if (value == null) return null;
switch (strategy) {
case PHONE:
return value.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2");
case ID_CARD:
return value.replaceAll("(\\d{4})\\d{10}(\\w{4})", "$1**********$2");
case NAME:
return value.length() > 1 ? value.charAt(0) + "*" + value.substring(2) : value;
default:
return value.length() > 2 ?
value.charAt(0) + "*".repeat(value.length()-2) + value.charAt(value.length()-1) : value;
}
}
}
2.4 实现AOP切面
@Aspect
@Component
public class SensitiveAspect {
// 拦截所有Controller方法
@Pointcut("execution(* com.example.controller..*(..))")
public void controllerPointcut() {}
// 后置处理返回结果
@AfterReturning(pointcut = "controllerPointcut()", returning = "result")
public Object doAfterReturning(Object result) {
if (result == null) return null;
return processObject(result);
}
// 递归处理对象
private Object processObject(Object obj) {
if (obj instanceof Collection) {
return processCollection((Collection<?>) obj);
} else if (obj instanceof Map) {
return processMap((Map<?, ?>) obj);
} else if (obj.getClass().isArray()) {
return processArray((Object[]) obj);
} else {
return processSingleObject(obj);
}
}
// 处理单个对象
private Object processSingleObject(Object obj) {
Class<?> clazz = obj.getClass();
for (Field field : clazz.getDeclaredFields()) {
if (field.isAnnotationPresent(Sensitive.class)) {
field.setAccessible(true);
try {
Object value = field.get(obj);
if (value instanceof String) {
SensitiveStrategy strategy = field.getAnnotation(Sensitive.class).strategy();
String desensitized = SensitiveUtil.desensitize((String) value, strategy);
field.set(obj, desensitized);
}
} catch (IllegalAccessException e) {
// 异常处理
}
}
}
return obj;
}
// 处理集合(省略Map/Array处理类似逻辑)
private Collection<?> processCollection(Collection<?> collection) {
return collection.stream()
.map(this::processObject)
.collect(Collectors.toList());
}
}
3. 实体类应用示例
public class User {
@Sensitive(strategy = SensitiveStrategy.NAME)
private String name;
@Sensitive(strategy = SensitiveStrategy.PHONE)
private String phone;
@Sensitive(strategy = SensitiveStrategy.ID_CARD)
private String idCard;
// 其他字段及getter/setter
}
4. 效果验证
@RestController
public class UserController {
@GetMapping("/user")
public User getUser() {
// 实际应从数据库获取
User user = new User();
user.setName("张三");
user.setPhone("13800138000");
user.setIdCard("110101199001011234");
return user; // 返回时自动脱敏
}
}
5. 输出结果
{
"name": "张*",
"phone": "138****8000",
"idCard": "1101**********1234"
}
6. 优化建议
- 性能优化:对高频调用接口添加缓存机制
- 嵌套对象:增强递归处理深度
- 自定义规则:支持通过注解参数自定义脱敏规则
- 线程安全:确保脱敏工具类的线程安全性
- 日志监控:添加脱敏操作日志记录
此方案通过注解+AOP实现无侵入式脱敏,无需修改业务逻辑代码,只需在字段添加注解即可自动生效,符合开闭原则。
更多推荐


所有评论(0)