用于加密/解密字段的Java Jackson Custom Polymorphc Deserializer

时间:2016-07-15 09:05:45

标签: java json encryption jackson deserialization

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

在内存中不需要加密。我希望以透明的方式实现对代码库的其余部分,所以我想把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,如果它们被注释,它们会反射地查找字段并发挥其魔力。序列化步骤就像一个魅力,我得到一个输出字符串,如:     {"的类型":"类型1"" encryptedField":" aGAzLwT47gE / QNlUuAhnJg ==&#34 ;, " unencryptedField":"明文"}

但解密很糟糕。我无法使其发挥作用:我不确定将多态性和解密结合起来要实现什么。

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

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

    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)构造函数,或者我真的尝试了不同的选项,但我一直陷入困境。

1 个答案:

答案 0 :(得分:0)

正如您所推断的那样,您需要@JsonTypeInfo多态性的东西。

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

关于“EncryptedDeserializer没有默认(无arg)构造函数”的特定错误 - 为什么不创建一个(即使它是private)?杰克逊通过反思将这些东西用于实例化。