数据去敏
一、背景
利用注解,反射,正则实现对象属性数据的去敏操作
二、实现
package com.hk.study.annotation;
import com.hk.study.constant.EncryptedType;
import java.lang.annotation.*;
/**
* 敏感数据模糊处理
*
* @author bigbeardhk
*/
@Retention(RetentionPolicy.RUNTIME) // 注解可以反射获取
@Target(ElementType.FIELD) // 注解只能打在成员属性上
@Documented
public @interface Encrypted {
EncryptedType encryptedType();
}
/**
* Copyright (c) bigbeardhk@163.com Corporation 2022. All Rights Reserved.
*/
package com.hk.study.util;
import com.hk.study.annotation.Encrypted;
import com.hk.study.constant.EncryptedType;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* 对实例对象的简单处理
*
* @Author : bigbeardhk
* @Date : 2022/05/04 16:23
**/
public class BeanUtil {
/**
* 数据去敏 - 对实例对象属性的去敏处理
*
* @param obj 需要处理的对象
* @throws IllegalAccessException 反射异常
*/
public static <T> void setDefaultDataByRead(T obj) throws IllegalAccessException {
// 获取父类及子类的所有成员变量
List<Field> allField = new ArrayList<>();
allField.addAll(Arrays.asList(obj.getClass().getDeclaredFields()));
allField.addAll(Arrays.asList(obj.getClass().getSuperclass().getDeclaredFields()));
// 循环所有属性
for (Field field : allField) {
field.setAccessible(true);
// 查找使用标记@Encrypted注解的属性
if (field.getAnnotation(Encrypted.class) != null) {
// field.get(obj)为该属性值
if (field.get(obj) != null) {
String value = null;
if (field.get(obj) instanceof String) {
value = (String) field.get(obj);
}
// 注解打在非String类型的属性上时,就不会进这个方法
if (value != null) {
// 若取出对应的为加密字段,就根据相对应的标识进行加密处理(应该抽取出来)
Encrypted encrypted = field.getAnnotation(Encrypted.class);
EncryptedType encryptedType = encrypted.encryptedType();
if (encryptedType == EncryptedType.NAME) {
if (value.length() == 2) {
field.set(obj, value.replaceAll(".(?=[\\u4e00-\\u9fa5])","*" ));
} else if (value.length() > 2) {
field.set(obj, value.replaceAll("(?<=[\\u4e00-\\u9fa5]).(?=[\\u4e00-\\u9fa5])", "*"));
}
} else {
field.set(obj, value.replaceAll(encryptedType.getCode(),
encryptedType.getValue()));
}
}
}
}
}
}
}
/**
* Copyright (c) bigbeardhk@163.com Corporation 2022. All Rights Reserved.
*/
package com.hk.study.vo.validator;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.hk.study.annotation.Encrypted;
import com.hk.study.constant.EncryptedType;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.hibernate.validator.constraints.Range;
import javax.validation.Valid;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.util.Date;
/**
* @Author : bigbeardhk
* @Date : 2022/05/01 19:51
**/
@Data
@ApiModel(value = "UserAO" , description = "用户模型")
public class UserEncrypted {
@Encrypted(encryptedType = EncryptedType.NAME)
@ApiModelProperty(value = "姓名")
private String name;
@Encrypted(encryptedType = EncryptedType.PHONE_NUMBER)
@ApiModelProperty(value = "手机号")
private String phone;
@Encrypted(encryptedType = EncryptedType.ID_CARD_NUMBER)
@ApiModelProperty(value = "身份证")
private String idCard;
public UserEncrypted() {
}
public UserEncrypted(String name, String phone, String idCard) {
this.name = name;
this.phone = phone;
this.idCard = idCard;
}
}
package com.hk.study.constant;
import lombok.Getter;
/**
* 数据去敏
*
* @author bigbeardhk
*/
@Getter
public enum EncryptedType {
// 身份证号码(18位)
ID_CARD_NUMBER("(\\d{4})\\d{10}(\\d{3}([\\d|x|X]{1})$)", "$1**********$2"),
// 姓名
NAME("(\\d{1}).*(\\d{1})", "$1*$2"),
// 手机号码
PHONE_NUMBER("(\\d{3})\\d{6}(\\d{2})", "$1******$2");
private String code;
private String value;
EncryptedType(String code, String value) {
this.code = code;
this.value = value;
}
}
结果:
Don't just do it. Show me your Blog. 语雀地址 : https://www.yuque.com/bigbeardhk/java