Java Jackson Custom Polymorphc Deserializer to encrypt/decry



我有某些对象的某些字段,当序列化以存储在数据库中时,需要加密。

它们在内存中不需要加密。我想以透明的方式对代码库的其余部分实现这一点,所以我想把 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":"plaintext"}

但是解密很糟糕。我无法让它工作:我不确定要实现什么东西来结合多态性和解密。

如果我删除@JsonDeserialize注释,并让杰克逊做它的事情,它会正确地反序列化多态,但使用加密字段。如果我尝试使用我的自定义反序列化程序,我会收到从 NPE 到杰克逊的各种错误。我想在反序列化器中实现的是这样的:

  1. 杰克逊,反序列化这个东西,因为你知道如何使用加密字段的类型信息
  2. 在返回之前,让我在实例上进行解密(不需要正确键入,我可以通过反射访问)。

这是我到目前为止所拥有的:

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 没有默认(没有 arg)构造函数而失败,或者我真的尝试了不同的选项,但我继续卡住。

正如

你所推导的那样,你需要多态性的@JsonTypeInfo东西。

自定义反序列化程序是实现加密逻辑的一种方法。 如果需要,您可以随时尝试在构造函数上进行反序列化的@JsonCreator注释(并在其中包含解密逻辑),并通过自定义 getter 上的@JsonProperty注释来处理加密。

关于"加密反序列化程序没有默认(没有arg)构造函数"的特定错误 - 为什么不创建一个(即使它是private)? 杰克逊使用这样的东西通过反射进行实例化。

最新更新