SpringBoot でのプライバシー データの感度解除のエレガントな実装 (Gitee ソース コードが提供されます)

前書き: 実際のプロジェクト開発では、一部のユーザーの個人情報が機密保護されない可能性があります。従来の方法の多くは、replace メソッドを使用して手動で置き換えますが、その結果、多くの冗長なコードが発生し、将来のメンテナンスが容易ではありません。今回は、SpringBoot でのシリアル化を通じてデータの非感作をエレガントに実現する方法を説明します。

目次

1. pom 依存関係をインポートする

2、DesensitizationEnum 列挙クラス

3. 減感カスタムアノテーション

4、DesensitizationSerialize 減感シリアライザ

5、ユーザーエンティティクラス

6. UserController リクエスト層

7、テストを実行してください

8.Giteeのソースコード

9. まとめ


1. pom 依存関係をインポートする

完全なコード:

    <dependencies>
        
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.18</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        
    </dependencies>

2、DesensitizationEnum 列挙クラス

DesensitizationSerialize シリアル化クラスでは、非感作アノテーションの型値、つまり DesensitizationEnum の型に従って、どの非感作メソッドを使用する必要があるかを決定します。

ここでは単純に 5 つの列挙型を定義します。

完全なコード:

package com.example.desensitization.constant;

public enum DesensitizationEnum {

    /**
     * 自定义
     */
    CUSTOM_RULE,
    
    /**
     * 身份证号码
     */
    ID_CARD_NO,

    /**
     * 电话号码
     */
    PHONE,

    /**
     * 地址
     */
    ADDRESS,

    /**
     * 银行卡号
     */
    BANK_CARD_NO,
}

3. 減感カスタムアノテーション

これはカスタム アノテーション@Desensitization で、感度を下げる必要があるフィールドをマークするために使用されます。

これには主に次のメタ アノテーションと属性が含まれます

1. @Target(ElementType.FIELD): このアノテーションがフィールドでのみ使用できることを示します。

2. @Retention(RetentionPolicy.RUNTIME): 注釈が実行時まで保持できることを示します。

3. @JacksonAnnotationsInside: これは Jackson メタアノテーションであり、アノテーションが Json シリアル化アノテーションとして使用できることを示します。

4. @JsonSerialize: アノテーションはシリアル化に DesensitizationSerialize を使用します。

5. DesensitizationEnum 型: 列挙内の感度解除タイプに対応する、感度解除が必要なタイプ。

6. int start/end:​​ オプションの開始位置と終了位置。感度解除タイプが文字列の場合に有効です。

完全なコード:

package com.example.desensitization.annotation;

import com.example.desensitization.constant.DesensitizationEnum;
import com.example.desensitization.serialize.DesensitizationSerialize;
import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
@JsonSerialize(using = DesensitizationSerialize.class)
public @interface Desensitization {

    DesensitizationEnum type();

    int start() default 0;

    int end() default 0;

}

4、DesensitizationSerialize 減感シリアライザ

1. JsonSerializer<String> の継承 JsonSerializer は、オブジェクトを JSON にシリアル化するコア メソッドを実装する Jackson のシリアライザー基本クラスで、文字列のカスタム シリアル化を実現するために継承されます。

2. ContextualSerializer インターフェイスの実装 ContextualSerializer を使用すると、コンテキストに基づいてシリアライザーをカスタマイズできます。このインターフェイスを実装した後、createContextual() メソッドを実装できます。

キーコード:

@AllArgsConstructor
@NoArgsConstructor
public class DesensitizationSerialize extends JsonSerializer<String> implements ContextualSerializer {

    private DesensitizationEnum type;

    private Integer start;

    private Integer end;
}

カスタム シリアライザー メソッドは、非侵入的で柔軟な感度の解除、ビジネス コードへの侵入ゼロを実現でき、Spring などのフレームワークに依存しないため、独立したアプリケーション サービスの作成に適しています。もちろん、AOP 実装にも適用可能なシナリオがあり、別の代替手段として使用できます。

createContextual()方法:

1. コントローラーの user() メソッドが呼び出され、User オブジェクトが構築されて返されます。

2. User オブジェクトの JSON シリアル化を開始するには、定義した DesensitizationSerialize の createContextual() メソッドが最初に呼び出されます。このエンティティ クラスが createContextual() メソッドによって処理された場合、このメソッドは今後使用されません。そして、serialize() メソッドが直接使用されます。

3. DesensitizationSerialize は、現在のクラス フィールドに @Desensitization アノテーションがあるかどうかを確認します。N 個ある場合は、アノテーションのタイプ、開始パラメーター、終了パラメーターに従って N 個の DesensitizationSerialize インスタンスを作成します。

キーコード:

@Override
    public JsonSerializer<?> createContextual(SerializerProvider serializerProvider, BeanProperty beanProperty)
            throws JsonMappingException {
        if (beanProperty != null) {
            // 获取当前正在处理的字段的类型,判断如果是 String 类型则进行后续脱敏逻辑处理
            if (Objects.equals(beanProperty.getType().getRawClass(), String.class)) {
                // 通过 beanProperty 获取在字段上标注的 @Desensitization 注解
                Desensitization desensitization = beanProperty.getAnnotation(Desensitization.class);
                // 如果没有就尝试获取类注解
                if (desensitization == null) {
                    desensitization = beanProperty.getContextAnnotation(Desensitization.class);
                }
                // 不为null
                if (desensitization != null) {
                    // 如果获取到了注解,则根据注解的 type、start 和 end 参数创建 DesensitizationSerialize 实例,这是脱敏处理的序列化器
                    return new DesensitizationSerialize(desensitization.type(), desensitization.start(),
                            desensitization.end());
                }
            }
            // 直接返回默认的序列化器
            return serializerProvider.findValueSerializer(beanProperty.getType(), beanProperty);
        }
        // 直接返回默认的序列化器
        return serializerProvider.findNullValueSerializer(null);
    }

シリアル化メソッド: 

JsonGenerator は、Jackjson が提供する JSON ジェネレーター クラスです。カスタム シリアライザーの Serialize() メソッドでは、JsonGenerator インスタンスが渡されます。Serialize() メソッドは、JsonGenerator を通じて、感度を解除された文字列を結果の JSON に書き込む必要があります。

CharSequenceUtil と DesensitizedUtil は両方とも hutool によって提供されるツール クラスです。

全体的なプロセスは次のとおりです。

1. アノテーションのパラメータに従って、感度解除戦略を動的に選択します。

2. Hutool に対応する感度解除関数を呼び出して文字列を処理します。

3. 感度解除の結果を JSON に書き込みます。

キーコード:

    @Override
    public void serialize(String s, JsonGenerator jsonGenerator, SerializerProvider serializerProvider)
            throws IOException {
        switch (type){
            //自定义
            case CUSTOM_RULE:
                jsonGenerator.writeString(CharSequenceUtil.hide(s, start, end));
                break;
            //身份证
            case ID_CARD_NO:
                jsonGenerator.writeString(DesensitizedUtil.idCardNum(s, 2, 6));
                break;
            //手机号
            case PHONE:
                jsonGenerator.writeString(DesensitizedUtil.mobilePhone(s));
                break;
            //地址
            case ADDRESS:
                jsonGenerator.writeString(DesensitizedUtil.address(s, 2));
                break;
            // 银行卡脱敏
            case BANK_CARD_NO:
                jsonGenerator.writeString(DesensitizedUtil.bankCard(s));
                break;
            default:
        }
    }

要約すると、全体的な実行ロジックは次のとおりです。

1. コントローラーはエンティティ オブジェクトを返します。

2. エンティティ オブジェクトが初めて感度を解除されると、createContextual() メソッドが呼び出されます。

3. 現在のエンティティ オブジェクトの Desensitization の注釈が付けられたすべての文字列フィールドを取得し、対応する DesensitizationSerialize インスタンスを作成し、Desensitization Serializer を実現します。

4. Serialize() メソッドでスイッチの処理ロジックを実行し、JsonGenerator が結果の JSON に感度を解除した文字列を書き込みます。

5. Json データを返します。

完全なコード:

package com.example.desensitization.serialize;

import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.DesensitizedUtil;
import com.example.desensitization.annotation.Desensitization;
import com.example.desensitization.constant.DesensitizationEnum;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import java.io.IOException;
import java.util.Objects;

@AllArgsConstructor
@NoArgsConstructor
public class DesensitizationSerialize extends JsonSerializer<String> implements ContextualSerializer {

    private DesensitizationEnum type;

    private Integer start;

    private Integer end;

    @Override
    public void serialize(String s, JsonGenerator jsonGenerator, SerializerProvider serializerProvider)
            throws IOException {
        switch (type){
            //自定义
            case CUSTOM_RULE:
                jsonGenerator.writeString(CharSequenceUtil.hide(s, start, end));
                break;
            //身份证
            case ID_CARD_NO:
                jsonGenerator.writeString(DesensitizedUtil.idCardNum(s, 2, 6));
                break;
            //手机号
            case PHONE:
                jsonGenerator.writeString(DesensitizedUtil.mobilePhone(s));
                break;
            //地址
            case ADDRESS:
                jsonGenerator.writeString(DesensitizedUtil.address(s, 2));
                break;
            // 银行卡脱敏
            case BANK_CARD_NO:
                jsonGenerator.writeString(DesensitizedUtil.bankCard(s));
                break;
            default:
        }
    }

    @Override
    public JsonSerializer<?> createContextual(SerializerProvider serializerProvider, BeanProperty beanProperty)
            throws JsonMappingException {
        if (beanProperty != null) {
            // 获取当前正在处理的字段的类型,判断如果是 String 类型则进行后续脱敏逻辑处理
            if (Objects.equals(beanProperty.getType().getRawClass(), String.class)) {
                // 通过 beanProperty 获取在字段上标注的 @Desensitization 注解
                Desensitization desensitization = beanProperty.getAnnotation(Desensitization.class);
                // 如果没有就尝试获取类注解
                if (desensitization == null) {
                    desensitization = beanProperty.getContextAnnotation(Desensitization.class);
                }
                // 不为null
                if (desensitization != null) {
                    // 如果获取到了注解,则根据注解的 type、start 和 end 参数创建 DesensitizationSerialize 实例,这是脱敏处理的序列化器
                    return new DesensitizationSerialize(desensitization.type(), desensitization.start(),
                            desensitization.end());
                }
            }
            // 直接返回默认的序列化器
            return serializerProvider.findValueSerializer(beanProperty.getType(), beanProperty);
        }
        // 直接返回默认的序列化器
        return serializerProvider.findNullValueSerializer(null);
    }
}

5、ユーザーエンティティクラス

感度を解除したいフィールドに @Desensitization(type = DesensitizationEnum. enumeration type) アノテーションを追加するだけです。

完全なコード:

package com.example.desensitization.domain;

import com.example.desensitization.annotation.Desensitization;
import com.example.desensitization.constant.DesensitizationEnum;
import lombok.Builder;
import lombok.Data;

@Data
@Builder
public class User {

    /**
     * 主键
     */
    private String id;

    /**
     * 用户名
     */
    private String name;

    /**
     * 身份证号码
     */
    @Desensitization(type = DesensitizationEnum.ID_CARD_NO)
    private String idCardNo;

    /**
     * 电话号码
     */
    @Desensitization(type = DesensitizationEnum.PHONE)
    private String phone;

    /**
     * 地址
     */
    @Desensitization(type = DesensitizationEnum.CUSTOM_RULE,start = 2,end = 5)
    private String address;

    /**
     * 银行卡号
     */
    @Desensitization(type = DesensitizationEnum.BANK_CARD_NO)
    private String bankCardNo;

}

6. UserController リクエスト層

完全なコード:

package com.example.desensitization.controller;

import com.example.desensitization.domain.User;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.UUID;

@RestController
@RequestMapping
public class UserController {

    @GetMapping("/user")
    public User user(){
        User user = User.builder()
                .id(UUID.randomUUID().toString())
                .name("张三").
                idCardNo("32089809285012823").
                phone("13919819285").
                bankCardNo("62427292012731238812").
                address("江苏省南通市").build();
        return user;
    }

}

7、テストを実行してください

ブラウザ直接アクセス: http://localhost:8080/user

個人情報が遮断されていることがわかります。

8.Giteeのソースコード

ソース コード アドレス: SpringBoot でのプライバシー データの感度解除のエレガントな実装

9. まとめ

上記は、SpringBoot でプライベート データをエレガントに制限解除する方法に関する私の完全なチュートリアルです。ご質問がある場合は、コメント エリアにメッセージを残してください。 

おすすめ

転載: blog.csdn.net/HJW_233/article/details/132307837