An annotation thing, data desensitization solved

This article mainly shares what data desensitization is, and how to elegantly use an annotation in a project to achieve data desensitization and empower the project. Hope it can help you.

What is data desensitization

Data desensitization is a technology that protects data privacy and security by removing or replacing some information in sensitive data. Its main purpose is to ensure that data can still be used in various scenarios, while protecting sensitive information and preventing data leakage and misuse. Data desensitization is usually used to process data sets containing personally identifiable information and other sensitive information, such as mobile phone numbers, names, addresses, bank cards, ID numbers, license plate numbers, and so on.

In the process of data desensitization, different algorithms and technologies are usually used to process data according to different needs and scenarios. For example, for an ID card number, you can use a masking algorithm (masking) to keep the first few digits, and replace the other digits with "X" or "*"; for a name, you can use a pseudonymization algorithm to replace the real name with Randomly generated pseudonym.

Next, I will talk about the data desensitization mask operation for everyone, let us learn together.

open whole

The following introduces to you the use of two different tool classes for data desensitization, and our topic today uses one annotation to solve the main two tool classes for data desensitization problems. Come and learn from me.

Use the Hutool tool class to implement data masking

For example, we now want to desensitize the data of the mobile phone number, the first three and the last four are not masked, and all others are masked with *

As shown in the code below,

We have defined a mobile phone number: 17677772345, which requires data desensitization.

Called Hutool's information desensitization tool class.

image-20230601084145280

Let's run it and see the result. A simple data desensitization is achieved.

image-20230601084159589

Hutool information desensitization tools

According to the demo above, you can see that I used Hutool's information desensitization tools to desensitize the mobile phone number mask. So let's take a look at Hutool's information desensitization tools.

Official website documents:

https://hutool.cn/docs/#/core/tools/information desensitization tool-DesensitizedUtil

Take a look at the introduction on the official website. It supports a variety of desensitized data types to meet most of our needs. If you need to customize, it also provides a custom method to achieve.

image-20230601084315876

The following is the desensitization rule of the definition number in it. Simple data desensitization can be achieved by calling directly. The reason for introducing it here is because the core of data desensitization is to use the tools provided by our Hutool. Implementation, support for custom hiding.

image-20230601084344604

Data serialization desensitization using Jackson

First create an entity class, this entity class has only one mobile phone number for testing.

Explanation of annotations:

  • @Data: The annotations of lombok generate get, set and other methods.
  • @JsonSerialize(using = TestJacksonSerialize.class): The function of this annotation is to customize serialization, which can be used on annotations, methods, fields, classes, runtime, etc., according to the provided serialization class Override method to implement custom serialization. You can take a look at the source code below, and friends who are interested can go to find out, and it can also solve many scenarios in our daily development.

image-20230601084406350


@Data
public class TestDTO implements Serializable {
    
    
    /**
     * 手机号
     */
    @JsonSerialize(using = TestJacksonSerialize.class)
    private String phone;
}

Then create a TestJacksonSerialize class to implement custom serialization.

This class mainly inherits JsonSerializer, because the type we need to serialize here is String generic, we choose String. Note that if you use this annotation on a class, this is the class you want to serialize.

Rewrite the serialization method, the implementation inside is very simple to call our Hutool tool class to desensitize the mobile phone number data.

public class TestJacksonSerialize extends JsonSerializer<String> {
    
    

    @Override
    @SneakyThrows
    public void serialize(String str, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) {
    
    
        // 使用我们的hutool工具类进行手机号脱敏
        jsonGenerator.writeString(DesensitizedUtil.fixedPhone(String.valueOf(str)));
    }
}

Let's test it, because this annotation is valid at runtime, we define an interface to test.

@RestController
@RequestMapping("/test")
public class TestApi {
    
    

    @GetMapping
    public TestDTO test(){
    
    
        TestDTO testDTO = new TestDTO();
        testDTO.setPhone("17677772345");
        return testDTO;
    }
}

image-20230601084424330

You can see that the test is successful. After the introduction of the above two tool classes, think about how we can define our own annotations through the two tool classes to achieve data desensitization.

Annotation realizes data desensitization

Let's think about it. Now that there are tool classes, how can we implement an annotation to solve data desensitization elegantly?

Please read the following, let me take you to learn together.

1. Define an annotation

Define a Desensitization annotation.

  • @Retention(RetentionPolicy.RUNTIME): Take effect at runtime.
  • @Target(ElementType.FIELD): Can be used on fields.
  • @JacksonAnnotationsInside: This annotation can be clicked in to see that it is a meta-annotation, which is mainly used by users to pack other annotations together.
  • @JsonSerialize: As mentioned above, the function of this annotation is to customize serialization, which can be used on annotations, methods, fields, classes, runtime, etc., according to the rewriting in the provided serialization class Method to implement custom serialization.

@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;
}

You can see that this annotation has three values, one is that the enumeration class defines our desensitized data type. A start position and an end position.

The enumeration class will be explained to you later. If you choose a custom type, the following start position and end position will take effect.

The start and end positions are parameters required by the custom masking implementation provided by our Hutool tool. You can see this method. It needs to be pointed out that this method hard-codes the mask value. If our scene needs other mask values, the implementation is also very simple. Copy out the source code of Hutool and replace its hard coding, and it can be realized.

image-20230601084440243

2. Create an enumeration class

This enumeration class is the type of our data desensitization, including most scenarios. And it can meet our daily development.


public enum DesensitizationTypeEnum {
    
    
    //自定义
    CUSTOMER,
    //用户id
    USER_ID,
    //中文名
    CHINESE_NAME,
    //身份证号
    ID_CARD,
    //座机号
    FIXED_PHONE,
    //手机号
    MOBILE_PHONE,
    //地址
    ADDRESS,
    //电子邮件
    EMAIL,
    //密码
    PASSWORD,
    //中国大陆车牌,包含普通车辆、新能源车辆
    CAR_LICENSE,
    //银行卡
    BANK_CARD
}

3. Create our custom serialization class

This class is the key to our data desensitization. It mainly inherits our JsonSerializer and implements my ContextualSerializer. The methods of both of them are rewritten.

  • @NoArgsConstructor: Lombok no-argument constructor generation.
  • @AllArgsConstructor: Lombok has parameter generation.
  • ContextualSerializer: This class is a serialization context class. It mainly solves the problem of obtaining some information about fields in our place. You can take a look at the source code. There are many implementation classes. The @JsonFormat annotation provided by Jackson also implements this class to obtain some information about fields. serialized. Friends who are interested can take a look at the source code to learn Jackson's implementation method and our implementation today.

Interpretation of the two rewritten methods:

  • serialize: Override to implement our serialization customization.
  • createContextual: rewrite the serialization context method, get some information from our fields to judge, and then return the instance. The specific code can be seen in the following code, there are comments.
@NoArgsConstructor
@AllArgsConstructor
public class DesensitizationSerialize extends JsonSerializer<String> implements ContextualSerializer {
    
    
    private DesensitizationTypeEnum type;

    private Integer startInclude;

    private Integer endExclude;
    @Override
    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:
        }

    }

    @Override
    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);
                // 为null
                if (desensitization == null) {
    
    
                    desensitization = beanProperty.getContextAnnotation(Desensitization.class);
                }
                // 不为null
                if (desensitization != null) {
    
    
                    // 创建定义的序列化类的实例并且返回,入参为注解定义的type,开始位置,结束位置。
                    return new DesensitizationSerialize(desensitization.type(), desensitization.startInclude(),
                            desensitization.endExclude());
                }
            }

            return serializerProvider.findValueSerializer(beanProperty.getType(), beanProperty);
        }
        return serializerProvider.findNullValueSerializer(null);
    }
}

4. Test

Create a test annotated DTO, this test is as follows.


@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;
}

New test interface:

	@GetMapping("/test-annotation")
	public TestAnnotationDTO testAnnotation() {
    
    
		TestAnnotationDTO testAnnotationDTO = new TestAnnotationDTO();
		testAnnotationDTO.setPhone("17677772345");
		testAnnotationDTO.setCustom("111111111111111111");
		testAnnotationDTO.setEmail("[email protected]");
		testAnnotationDTO.setIdCard("4444199810015555");
		return testAnnotationDTO;
	}

Test it to see the effect. As shown in the picture below, perfect!

image-20230601084500341

Project pom file

<?xml version="1.0" encoding="UTF-8"?>
<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>

Summarize

Well, data desensitization is still widely used in actual enterprise development, and it is more practical. Let's learn together, it is another new skill.
At the same time, with the tools, assembling the tools into a new tool for your own use is the ability.
If it is helpful to you, leave a three-link

Guess you like

Origin blog.csdn.net/weixin_40379712/article/details/130981103