注釈の問題、データの感度低下が解決されました

この記事では主に、データの匿名化とは何か、およびプロジェクトで注釈をエレガントに使用してデータの匿名化を実現し、プロジェクトを強化する方法について説明します。お役に立てれば幸いです。

データの感度解除とは何ですか

データの非感作化は、機密データの一部の情報を削除または置き換えることにより、データのプライバシーとセキュリティを保護するテクノロジーです。その主な目的は、機密情報を保護し、データの漏洩や悪用を防止しながら、さまざまなシナリオでデータを確実に使用できるようにすることです。データの感作解除は通常、個人を特定できる情報や、携帯電話番号、名前、住所、銀行カード、ID 番号、ナンバー プレート番号などのその他の機密情報を含むデータ セットを処理するために使用されます。

データの感度解除のプロセスでは、通常、さまざまなニーズやシナリオに従ってデータを処理するために、さまざまなアルゴリズムとテクノロジーが使用されます。たとえば、ID カード番号の場合は、マスキング アルゴリズム (マスキング) を使用して最初の数桁を保持し、他の桁を「X」または「*」に置き換えることができます。名前の場合は、仮名化アルゴリズムを使用して、本名をランダムに生成された仮名に置き換えます。

次に、皆さんにデータ不感作マスク操作についてお話しますので、一緒に学びましょう。

全体を開く

以下では、データの感度を下げるための 2 つの異なるツール クラスの使用方法を紹介します。今日のトピックでは、1 つの注釈を使用して、データの感度を下げる問題に対する主要な 2 つのツール クラスを解決します。来て私から学びましょう。

Hutool ツール クラスを使用してデータ マスキングを実装する

たとえば、携帯電話番号のデータの感度を下げたいとします。最初の 3 つと最後の 4 つはマスクされず、他のすべては * でマスクされます。

以下のコードに示すように、

データの感度を解除する必要がある携帯電話番号 17677772345 を定義しました。

Hutool の情報非感作ツール クラスと呼ばれます。

画像-20230601084145280

実行して結果を見てみましょう。簡単なデータの非感作が実現されます。

画像-20230601084159589

Hutool 情報の感度を解除するツール

上記のデモによると、Hutool の情報感度を下げるツールを使用して携帯電話番号マスクを感度を解除したことがわかります。それでは、Hutool の情報非感作ツールを見てみましょう。

公式ウェブサイトのドキュメント:

https://hutool.cn/docs/#/core/tools/information 感度解除ツール-DesensitizedUtil

公式 Web サイトの紹介をご覧ください。ほとんどのニーズを満たすために、さまざまな感度の低いデータ型をサポートしています。カスタマイズが必要な場合は、それを実現するためのカスタム方法も提供されています。

画像-20230601084315876

以下は、その中の定義番号の非感作ルールです 直接呼び出すことで簡単なデータの非感作が実現できます ここで紹介する理由は、データの非感作の中核が当社の Hutool が提供するツールを使用することであるためです 実装、サポートカスタムの非表示。

画像-20230601084344604

Jackson を使用したデータシリアル化の感度解除

まずエンティティ クラスを作成します。このエンティティ クラスにはテスト用の携帯電話番号が 1 つだけあります。

注釈の説明:

  • @Data: lombok のアノテーションは get、set などのメソッドを生成します。
  • @JsonSerialize(using = TestJacksonSerialize.class): このアノテーションの機能は、提供されたシリアル化クラスに従って、アノテーション、メソッド、フィールド、クラス、ランタイムなどで使用できるシリアル化をカスタマイズすることです。カスタム シリアル化を実装するメソッドをオーバーライドします。 。以下のソース コードを見て、興味のある友人が調べに行くと、日常の開発における多くのシナリオを解決することもできます。

画像-20230601084406350


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

次に、TestJacksonSerialize クラスを作成してカスタム シリアル化を実装します。

このクラスは主に JsonSerializer を継承します。ここでシリアル化する必要がある型は String ジェネリックであるため、String を選択します。このアノテーションをクラスで使用する場合、これがシリアル化するクラスであることに注意してください。

シリアル化メソッドを書き換えます。内部の実装は非常に簡単で、Hutool ツール クラスを呼び出して携帯電話番号データの感度を解除します。

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

このアノテーションは実行時に有効なので、テストするインターフェイスを定義します。

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

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

画像-20230601084424330

テストが成功したことがわかります。上記の 2 つのツール クラスを導入した後、2 つのツール クラスを使用して独自のアノテーションを定義し、データの非感作を実現する方法を考えてみましょう。

アノテーションによりデータの匿名化が実現

ツール クラスがあるので、データの非感作をエレガントに解決するためのアノテーションをどのように実装できるでしょうか?

以下を読んで、一緒に学びましょう。

1. アノテーションを定義する

Desensitization アノテーションを定義します。

  • @Retention(RetentionPolicy.RUNTIME): 実行時に有効になります。
  • @Target(ElementType.FIELD): フィールドで使用できます。
  • @JacksonAnnotationsInside: この注釈をクリックすると、それがメタ注釈であることが確認できます。メタ注釈は、主にユーザーが他の注釈をまとめてパックするために使用します。
  • @JsonSerialize: 前述したように、このアノテーションの機能はシリアル化をカスタマイズすることであり、カスタム シリアル化を実装するために提供されたシリアル化クラス メソッドの書き換えに従って、アノテーション、メソッド、フィールド、クラス、ランタイムなどで使用できます。

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

この注釈には 3 つの値があることがわかります。1 つは、列挙型クラスが感度を下げたデータ型を定義していることです。開始位置と終了位置。

列挙型クラスについては後述しますが、カスタム型を選択した場合、以下の開始位置と終了位置が有効になります。

開始位置と終了位置は、Hutool ツールが提供するカスタム マスキング実装に必要なパラメーターです。このメソッドはご覧のとおりですが、このメソッドはマスク値をハードコーディングしていることに注意する必要があります。シーンに他のマスク値が必要な場合も、実装は非常に簡単で、Hutool のソースコードをコピーしてハードコーディングを置き換えるだけで実現できます。

画像-20230601084440243

2.列挙型クラスを作成する

この列挙クラスは、ほとんどのシナリオを含むデータの感度解除のタイプです。そしてそれは私たちの日々の成長に応えることができます。


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

3. カスタムシリアル化クラスを作成します。

このクラスはデータの感度を下げるための鍵となります。これは主に JsonSerializer を継承し、ContextualSerializer を実装します。両方のメソッドが書き直されました。

  • @NoArgsConstructor: Lombok の引数なしのコンストラクターの生成。
  • @AllArgsConstructor: Lombok にはパラメーター生成があります。
  • ContextualSerializer: このクラスはシリアル化コンテキスト クラスです。主にフィールドに関する情報を代わりに取得する問題を解決します。ソース コードを確認できます。多くの実装クラスがあります。Jackson によって提供される @JsonFormat アノテーションも実装されていますこのクラスはフィールドに関する情報を取得します。興味のある友人は、ソース コードを見て、Jackson の実装方法と今日の実装を学ぶことができます。

書き換えられた 2 つのメソッドの解釈:

  • Serialize: シ​​リアル化のカスタマイズを実装するためにオーバーライドします。
  • createContextual: シリアル化コンテキスト メソッドを書き換え、フィールドから情報を取得して判断し、インスタンスを返します。具体的なコードは次のコードで確認できます。コメントもあります。
@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. テスト

注釈付きの DTO を作成します。このテストは次のとおりです。


@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("[email protected]");
		testAnnotationDTO.setIdCard("4444199810015555");
		return testAnnotationDTO;
	}

テストして効果を確認してください。下の写真のように、完璧です!

画像-20230601084500341

プロジェクトpomファイル

<?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>

要約する

データの非感作化は、実際の企業開発において依然として広く使用されており、より実用的です。これも新しいスキルですので、一緒に学びましょう。
同時に道具は、それを組み立てて自分専用の新しい道具にする能力です。
お役に立ちましたら、リンクを 3 つ残してください

おすすめ

転載: blog.csdn.net/weixin_40379712/article/details/130981103