【JAVA】jacksonを利用したデータマスキング

2022.08.10

2022.08.10

Fabeee社員ブログ


こんにちは、レオです!
個人情報漏洩などのニュースが人々を怖がらせる世の中、「自分たちのシステム大丈夫でしょうか?」っと真夏の熱帯夜みたいに眠れない日々を過ごしているエンジニアいませんか?この記事が、このような人たちのため、微力でもお助けになるようであれば嬉しいです。

なぜマスキング?

当たり前の話ですが、不必要なものを載せないのが一番安全です。ただし、意外と見落としやすい罠もあります、それがログです。リクエスト内容確認とかエラー調査とか役に立ちますが、知らない内に溜まった大量なログの中に個人情報含まれたら、ゾッとしませんか?こんな時に自動的にマスキングできれば安心ですよね。

jacksonでマスキング

JAVA経験ある人にとって、jacksonは珍しいものではないでしょう。ObjectからString、StringからObject簡単に変換することができる、今回はそのjacksonのserializerを使ったマスキング方法を紹介しましょう。

構成と実装

Mask.java

実際どの部分をマスキングすべきなのかを明示するためのあのてアノテーションのクラス。
今回はStringをマスキングする例です。

// Mask.java

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Mask {
    String value() default "***"; // アノテーション付けた文字列を"***"に置換
}

アノテーションの使い方はマスキングしたいフィールドにつけるだけ。

// Samlpe.java
class Samlpe {
    @Mask
    private String maskString; // マスキング対象

    private String noMaskString;
}

MaskStringSerializer.java

jacksonのSerializerクラスです、アノテーションを認識して、マスキングのルールなどはこのクラスの役割です。

// MaskStringSerializer.java
public class MaskStringSerializer extends StdSerializer implements ContextualSerializer {
    private Mask annotation;

    public MaskStringSerializer() {
        super(String.class);
    }

    public MaskStringSerializer(Mask maskAnnotation) {
        super(String.class);
        this.annotation = maskAnnotation;
    }

    public void serialize(String s, JsonGenerator jsonGenerator,
        SerializerProvider serializerProvider) throws IOException {
                // マスキングする条件はアノテーション付けること、もちろん他の条件追加しても構いません
        if (annotation != null && s != null && !s.isEmpty()) { 
            jsonGenerator.writeString(annotation.value());
        } else {
            jsonGenerator.writeString(s);
        }
    }

        // Maskというアノテーションついてるかどうかの判断はここでします、アノテーション種類増えた時ここ対応しないと認識されませんので要注意
    public JsonSerializer createContextual(SerializerProvider serializerProvider,
        BeanProperty beanProperty) throws JsonMappingException {
        Mask annotation = null;
        if (beanProperty != null) {
            annotation = beanProperty.getAnnotation(Mask.class);
        }
        return new MaskStringSerializer(annotation);
    }
}

使ってみよう

いつものjacksonのObjectMapperに先程のSerializerを入れるだけです。

final SimpleModule simpleModule = new SimpleModule();
simpleModule.addSerializer(String.class, new MaskStringSerializer());

final ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(simpleModule);

これでobjectMapperにはSerializer仕込み済みです、ObjectからStringに変換する時Serializerに書いたルール通りにマスキングできます。

String str = objectMapper.writeValueAsString(data);

 

まとめ

今回紹介するのは文字列のマスキングの一例です、もちろん数字とかObjectそのものも対象にするとこも可能です、マスキングのルールと内容もカスタマイズ可能なので、気になる人は色々試してみてはいかがでしょうか?

 

最後まで読んでいただきありがとうございました!

Fabeee編集部

Fabeee編集部

こちらの記事はFabeee編集部が執筆しております。