DBに格納するためにシリアル化する際に暗号化する必要がある特定のオブジェクトの特定のフィールドがあります。Java Jacksonカスタムポリモルファスデシリアライザを使用してフィールドを暗号化/復号化する
メモリ内で暗号化する必要はありません。私はこれをコードベースの残りの部分に透過的に行いたいので、enc/decステップをser/deserレベルに置くことを考えました。
汎用的であるためには、私はインターフェイスおよび注釈を作成しました:
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "__TYPE__")
@JsonSubTypes({
@JsonSubTypes.Type(value = Type1.class, name = "Type1"),
@JsonSubTypes.Type(value = Type2.class, name = "Type2"),
@JsonSubTypes.Type(value = Type3.class, name = "Type3")
})
@JsonSerialize(using=EncryptedSerializer.class)
@JsonDeserialize(using=EncryptedDeserializer.class)
public interface EncryptedType {}
と
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface EncryptedField {}
アイデアは、クラスがにマッチするように、空のインターフェイスを実装するということですカスタムser/deserは、フィールドを反射的に見つけ、注釈が付いている場合はその魔法を実行します。直列化ステップは、魔法のように動作し、私のような出力文字列を取得: {」TYPE ":" のType1" 、 "encryptedField": "aGAzLwT47gE/QNlUuAhnJg =="、 "unencryptedField": "平文"}
をしかし、復号化はひどいです。私はそれを働かせることはできません:多形性と解読を組み合わせるために実装すべきものがわかりません。
@JsonDeserializeアノテーションを削除して、ジャクソンにそれをさせても、正しくポリモフィックではなく暗号化されたフィールドでデシリアライズされます。カスタムデシリアライザを使用しようとすると、NPEからすべての種類のエラーが発生します。あなたはどのよう
- ジャクソンは、(私はインスタンス上で私の復号化をやらせる、この事をデシリアライズ:私は私のデシリアライザで達成したいことは何かに似ています正確に入力する必要はなく、私は反射を通してアクセスすることができます)。
public class EncryptedDeserializer extends StdDeserializer<EncryptedType> { [..super etc..] @Override public EncryptedType deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException { return null; } @Override public EncryptedType deserializeWithType(JsonParser p, DeserializationContext ctxt, TypeDeserializer typeDeserializer) throws IOException { EncryptedType newInstance = super.deserializeWithType(p, ctxt, typeDeserializer); Field[] fields = newInstance.getClass().getDeclaredFields(); for (Field field : fields) { if (field.isAnnotationPresent(EncryptedField.class)) { boolean accessibility = field.isAccessible(); field.setAccessible(true); try { field.set(newInstance, ApplicationContextRegister.getApplicationContext().getBean(TextEncryptionService.class).decrypt((String) field.get(newInstance))); } catch (Exception e) { log.error("Could not decryption field " + field.getName() + " of " + newInstance + ". Skipping decryption"); } field.setAccessible(accessibility); } } return newInstance; }
しかし、これはエラーで失敗するかEncryptedDeserializer文句はデフォルト(引数なし)コンストラクタを持っていないか、私は本当にさまざまなオプションを試してみましたが、私は得ることに保つ:ここ
githubのjackson-cryptoはこれを行いますが、少し異なる出力を生成します。 Beanの直列化修飾子を使用して、他の(シ)シリアライザをラップします。これのコードはここにあります(https://github.com/meltmedia/jackson-crypto/tree/develop/src/main/java/com/meltmedia/jackson/crypto)。 –