什么是数据脱敏???
数据脱敏(Data Masking)是一种数据安全技术,旨在通过预先设定的规则和算法,对原始数据中包含的敏感信息进行变形处理,使得这些信息在非生产环境(例如开发、测试、分析或培训场景)中使用时,既能保持原有数据格式和业务逻辑的真实性,又能有效保护个人隐私和商业机密不被泄露。
在实施数据脱敏时,对诸如身份证号、手机号、银行卡号、个人姓名、家庭住址、电子邮件地址、医疗记录等敏感信息采取替换、遮盖、乱序、加密、截断等手段进行处理,以防止这些敏感信息在未经授权的情况下被识别或滥用。
具体脱敏规则可以包括但不限于:
-
替换:例如将身份证号的部分数字替换为“*”或随机数。
-
随机化:例如生成与真实数据格式相符但与原始数据无关的新数据。
-
固定模式脱敏:例如保留电话号码的区号和最后几位,其余部分替换。
-
加密:对数据进行不可逆或可逆加密,仅在必要时解密。
-
假名化:用虚构的名字替换真实姓名。
代码实现:主要是使用hutool中的脱敏方法(DesensitizedUtil)来实现
1、首先建立一个spring boot项目
<dependency><groupId>cn.hutool</groupId><artifactId>hutool-core</artifactId><version>5.8.16</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><!--json模块--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-json</artifactId></dependency>
2、创建注解Desensitization
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
//@Target用于限制自定义注解可以应用于哪些程序元素
//ElementType.FIELD:可以应用于字段、枚举常量声明。
@JacksonAnnotationsInside
//作用是将一组注解合并到一个新的注解中。当这个新注解被应用到类或字段上时,实际上相当于应用了它所包含的所有注解。
@JsonSerialize(using = DesensitizationSerialize.class)
//用于自定义 Java 对象如何序列化成 JSON 格式
public @interface Desensitization {/*** 脱敏数据类型,只要在CUSTOMER的时候,startInclude和endExclude生效*/DesensitizationTypeEnum type() default DesensitizationTypeEnum.CUSTOMER;/*** 开始位置(包含)*/int startInclude() default 0;/*** 结束位置(不包含)*/int endExclude() default 0;
}
3.建立脱敏需要的枚举类
public enum DesensitizationTypeEnum {//自定义CUSTOMER,//用户idUSER_ID,//中文名CHINESE_NAME,//身份证号ID_CARD,//座机号FIXED_PHONE,//手机号MOBILE_PHONE,//地址ADDRESS,//电子邮件EMAIL,//密码PASSWORD,//中国大陆车牌,包含普通车辆、新能源车辆CAR_LICENSE,//银行卡BANK_CARD
}
4.创建自定义的序列化脱敏类
@NoArgsConstructor
@AllArgsConstructor
public class DesensitizationSerialize extends JsonSerializer<String> implements ContextualSerializer {// 保存敏感信息处理规则的枚举private DesensitizationTypeEnum type;private Integer startInclude;private Integer endExclude;// JsonGenerator 主要用于生成 JSON 数据并将其输出到各种类型的输出流//serialize 方法本身并不直接提供数据脱敏功能,它主要是为了将表单数据转换为可传输的字符串格式@Overridepublic void serialize(String str, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {switch (type) {//自定义 Java 对象如何序列化成 JSON 格式// 自定义类型脱敏case CUSTOMER://通过使用 CharSequenceUtil 类,开发者可以更加方便地进行字符串相关的编程工作,避免了重复编写基础的字符串处理逻辑jsonGenerator.writeString(CharSequenceUtil.hide(str,startInclude,endExclude));break;// userId脱敏case USER_ID:jsonGenerator.writeString(String.valueOf(DesensitizedUtil.userId()));break;// 中文姓名脱敏case CHINESE_NAME:jsonGenerator.writeString(DesensitizedUtil.chineseName(String.valueOf(str)));break;// 身份证脱敏case ID_CARD:jsonGenerator.writeString(DesensitizedUtil.idCardNum(String.valueOf(str), 1, 2));break;// 固定电话脱敏case FIXED_PHONE:jsonGenerator.writeString(DesensitizedUtil.fixedPhone(String.valueOf(str)));break;// 手机号脱敏case MOBILE_PHONE:jsonGenerator.writeString(DesensitizedUtil.mobilePhone(String.valueOf(str)));break;// 地址脱敏case ADDRESS:jsonGenerator.writeString(DesensitizedUtil.address(String.valueOf(str), 8));break;// 邮箱脱敏case EMAIL:jsonGenerator.writeString(DesensitizedUtil.email(String.valueOf(str)));break;// 密码脱敏case PASSWORD:jsonGenerator.writeString(DesensitizedUtil.password(String.valueOf(str)));break;// 中国车牌脱敏case CAR_LICENSE:jsonGenerator.writeString(DesensitizedUtil.carLicense(String.valueOf(str)));break;// 银行卡脱敏case BANK_CARD:jsonGenerator.writeString(DesensitizedUtil.bankCard(String.valueOf(str)));break;default:}}//BeanProperty 参数代表Java Bean中正在被反序列化的属性, 初始化或定制该反序列化器的行为。@Overridepublic JsonSerializer<?> createContextual(SerializerProvider serializerProvider, BeanProperty beanProperty) throws JsonMappingException {if (beanProperty != null) {// 判断数据类型是否为String类型if (Objects.equals(beanProperty.getType().getRawClass(), String.class)) {// 获取定义的注解Desensitization desensitization = beanProperty.getAnnotation(Desensitization.class);// 为nullif (desensitization == null) {//就可以通过 getContextAnnotation 来找到这个注解并据此调整属性的序列化或反序列化行为desensitization = beanProperty.getContextAnnotation(Desensitization.class);}// 不为nullif (desensitization != null) {// 创建定义的序列化类的实例并且返回,入参为注解定义的type,开始位置,结束位置。return new DesensitizationSerialize(desensitization.type(), desensitization.startInclude(),desensitization.endExclude());}}//查找和提供合适的序列化器(JsonSerializer)来处理给定类型的数据return serializerProvider.findValueSerializer(beanProperty.getType(), beanProperty);}return serializerProvider.findNullValueSerializer(null);}
}
5.测试:创建实例类添加脱敏注解
@Data
public class TestAnnotationDTO implements Serializable {/*** 自定义*/@Desensitization(type = DesensitizationTypeEnum.CUSTOMER,startInclude = 5,endExclude = 10)private String custom;/*** 手机号*/@Desensitization(type = DesensitizationTypeEnum.MOBILE_PHONE)private String phone;/*** 邮箱*/@Desensitization(type = DesensitizationTypeEnum.EMAIL)private String email;/*** 身份证*/@Desensitization(type = DesensitizationTypeEnum.ID_CARD)private String idCard;}
6、测试类
@RestController
@RequestMapping("/test")
public class TestApi {@GetMapping("/test-annotation")public TestAnnotationDTO testAnnotation(){TestAnnotationDTO testAnnotationDTO = new TestAnnotationDTO();testAnnotationDTO.setPhone("17634388363");testAnnotationDTO.setCustom("111111111111111111");testAnnotationDTO.setEmail("1433926101@qq.com");testAnnotationDTO.setIdCard("4444199810015555");cereturn testAnnotationDTO;}}
7、启动项目:http://localhost:8080/test/test-annotation