首页 > 数据治理 > 数据治理 > 数据脱敏?看我一行注解搞定!
原文作者:佳庆,链接:juejin.cn/post/7225218026097852472
本文主要分享什么是数据脱敏,如何优雅的在项目中运用一个注解实现数据脱敏,为项目进行赋能。希望能给你们带来帮助。
数据脱敏是一种通过去除或替换敏感数据中的部分信息,以保护数据隐私和安全的技术。其主要目的是确保数据仍然可以在各种场景中使用,同时保护敏感信息,防止数据泄露和滥用。数据脱敏通常用于处理包含个人身份信息和其他敏感信息的数据集,如手机号、姓名、地址、银行卡、身份证号、车牌号等等。
在数据脱敏过程中,通常会采用不同的算法和技术,以根据不同的需求和场景对数据进行处理。例如,对于身份证号码,可以使用掩码算法(masking)将前几位数字保留,其他位用“X”或"*"代替;对于姓名,可以使用伪造(pseudonymization)算法,将真实姓名替换成随机生成的假名。
下面我讲为大家带来数据脱敏掩码操作,让我们一起学起来吧。
比喻说我们现在要对手机号进行数据脱敏,前三后四不掩码,其他全部用 * 进行掩码
如下图代码所示,
我们定义了一个手机号:17677772345,需要进行数据脱敏。
调用的 Hutool 的信息脱敏工具类。


官网文档:
https://hutool.cn/docs/#/core/工具类/信息脱敏工具-DesensitizedUtil
看一下官网的介绍,支持多种脱敏数据类型,满足我们大部分需求,如果需要自定义还提供了自定义的方法实现。

下面是里面定义号的脱敏规则,直接调用就可以实现简单的数据脱敏,这里给大家介绍是因为我们今天要给大家带来的注解实现数据脱敏核心就是利用我们的 Hutool 提供的工具类实现,支持自定义隐藏。


@Datapublic class TestDTO implements Serializable { /** * 手机号 */ @JsonSerialize(using = TestJacksonSerialize.class) private String phone;}然后创建一个 TestJacksonSerialize 类实现自定义序列化。
此类主要继承 JsonSerializer,因为我们这里需要序列化的类型是 String 泛型就选择 String。注意如果你使用此注解作用在类上的话,这里就是你要序列化的类。
重写序列化方法,里面的实现很简单就是调用我们的 Hutool 工具类进行手机号数据脱敏。
public class TestJacksonSerialize extends JsonSerializer<String> {public void serialize(String str, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) {// 使用我们的hutool工具类进行手机号脱敏jsonGenerator.writeString(DesensitizedUtil.fixedPhone(String.valueOf(str)));}}
让我们测试一下吧,因为此注解是运行时生效,我们定义一个接口来测试。
("/test")public class TestApi {public TestDTO test(){TestDTO testDTO = new TestDTO();testDTO.setPhone("17677772345");return testDTO;}}

@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.FIELD)@JacksonAnnotationsInside@JsonSerialize(using = DesensitizationSerialize.class)public @interface Desensitization {/*** 脱敏数据类型,只要在CUSTOMER的时候,startInclude和endExclude生效*/DesensitizationTypeEnum type() default DesensitizationTypeEnum.CUSTOMER;/*** 开始位置(包含)*/int startInclude() default 0;/*** 结束位置(不包含)*/int endExclude() default 0;}
可以看到此注解有三个值,一个是枚举类定义了我们的脱敏数据类型。一个开始位置,一个结束位置。
枚举类待会给大家讲解,如果选择了自定义类型,下面的开始位置,结束位置才生效。
开始结束位置是我们 Hutool 工具提供的自定义脱敏实现需要的参数。可以看此方法,需要提出一点的是此方法硬编码了掩码值。如果我们的场景需要其他掩码值的话实现也很简单,把 Hutool 的源码拷出来,代替他的硬编码,就可以实现。

public enum DesensitizationTypeEnum { //自定义 CUSTOMER, //用户id USER_ID, //中文名 CHINESE_NAME, //身份证号 ID_CARD, //座机号 FIXED_PHONE, //手机号 MOBILE_PHONE, //地址 ADDRESS, //电子邮件 EMAIL, //密码 PASSWORD, //中国大陆车牌,包含普通车辆、新能源车辆 CAR_LICENSE, //银行卡 BANK_CARD}public class DesensitizationSerialize extends JsonSerializer<String> implements ContextualSerializer {private DesensitizationTypeEnum type;private Integer startInclude;private Integer endExclude;public void serialize(String str, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {switch (type) {// 自定义类型脱敏case CUSTOMER: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:}}public 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) {desensitization = beanProperty.getContextAnnotation(Desensitization.class);}// 不为nullif (desensitization != null) {// 创建定义的序列化类的实例并且返回,入参为注解定义的type,开始位置,结束位置。return new DesensitizationSerialize(desensitization.type(), desensitization.startInclude(),desensitization.endExclude());}}return serializerProvider.findValueSerializer(beanProperty.getType(), beanProperty);}return serializerProvider.findNullValueSerializer(null);}}
@Datapublic 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;}新增测试接口:
@GetMapping("/test-annotation")public TestAnnotationDTO testAnnotation(){ TestAnnotationDTO testAnnotationDTO = new TestAnnotationDTO(); testAnnotationDTO.setPhone("17677772345"); testAnnotationDTO.setCustom("111111111111111111"); testAnnotationDTO.setEmail("1433926101@qq.com"); testAnnotationDTO.setIdCard("4444199810015555"); return testAnnotationDTO;}测试一下看看效果。如下图所示,完美!

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.10</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.jiaqing</groupId><artifactId>tool-desensitization</artifactId><version>0.0.1-SNAPSHOT</version><name>tool-desensitization</name><description>数据脱敏</description><properties><java.version>1.8</java.version><hutool.version>5.8.5</hutool.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>cn.hutool</groupId><artifactId>hutool-core</artifactId><version>${hutool.version}</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!--json模块--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-json</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><excludes><exclude><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></exclude></excludes></configuration></plugin></plugins></build></project>
今天给大家带来的是如何实现一个注解进行数据脱敏。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70024922/viewspace-2965501/ ,如需转载,请注明出处,否则将追究法律责任。