杰克逊模块解串器未称为

问题描述

我正在尝试在Spring Boot应用程序中编写Jackson解串器模块。 主要原因是使用定制的Jackson解串器对传入请求中的密码进行加密。 加密属性由spring组件CipherInterface

提供

我正在尝试从this获得解决方案,但仍未调用我的自定义解串器。 始终不调用基于此的StringDeserializer而不执行加密

预先感谢

注释:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@JacksonAnnotation
public @interface Encrypted {
}

带有要加密字段的请求正文

@Value
public class CardCounterDecreaseRequest {
    @Encrypted
    private final String pinValue;
}

Jackson配置

    @Bean
    ObjectMapper unrestrictObjectMapper(final CipherInterface cipherInterface) {
        return JsonMapper.builder()
                .enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS)
                .enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES)
                .enable(SerializationFeature.INDENT_OUTPUT)
                .enable(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES)
                .enable(DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS)
                .disable(DeserializationFeature.FAIL_ON_MISSING_EXTERNAL_TYPE_ID_PROPERTY)
                .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
                .disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE)
                .disable(SerializationFeature.FAIL_ON_EMPTY_BEANS)
                .disable(DeserializationFeature.FAIL_ON_UNKNowN_PROPERTIES)
                .disable(DeserializationFeature.ACCEPT_FLOAT_AS_INT)
                .visibility(PropertyAccessor.ALL,JsonAutoDetect.Visibility.NONE)
                .visibility(PropertyAccessor.FIELD,JsonAutoDetect.Visibility.ANY)
                .addModules(new EncryptionModule(cipherInterface),new JavaTimeModule(),new VavrModule(),new ParanamerModule())
                .build();
    }

模块:

public class EncryptionModule extends SimpleModule {

    private final CipherInterface cipher;


    public EncryptionModule(final CipherInterface cipher) {
        super();
        this.cipher = cipher;
    }

    @Override
    public void setupModule(final SetupContext context) {
        context.addBeanDeserializerModifier(new EncryptedDeserializerModifier(cipher));
    }

}

public class EncryptedDeserializerModifier extends BeanDeserializerModifier {

    private final CipherInterface cipher;

    public EncryptedDeserializerModifier(final CipherInterface cipher) {
        super();
        this.cipher = cipher;
    }

    @Override
    public BeanDeserializerBuilder updateBuilder(final DeserializationConfig config,final BeanDescription beanDesc,final BeanDeserializerBuilder builder) {

        final Iterator<SettableBeanProperty> it = builder.getProperties();

        while (it.hasNext()) {
            final SettableBeanProperty prop = it.next();
            if (null != prop.getAnnotation(Encrypted.class)) {
                final JsonDeserializer<Object> current = prop.getValueDeserializer(); // always  returns null
                final EncryptedJsonDeserializer encryptedDeserializer = new EncryptedJsonDeserializer(cipher,current);
                final SettableBeanProperty propWithEncryption = prop.withValueDeserializer(encryptedDeserializer);
                builder.addOrReplaceProperty(propWithEncryption,true);
            }
        }
        return builder;
    }

}

最后是反序列化器:

public class EncryptedJsonDeserializer extends JsonDeserializer<Object> implements ContextualDeserializer {

    private final CipherInterface service;
    private final JsonDeserializer<Object> baseDeserializer;
    private final BeanProperty property;

    public EncryptedJsonDeserializer(final CipherInterface service,final JsonDeserializer<Object> baseDeserializer) {
        this.service = service;
        this.baseDeserializer = baseDeserializer;
        this.property = null;
    }

    public EncryptedJsonDeserializer(final CipherInterface service,final JsonDeserializer<Object> wrapped,final BeanProperty property) {
        this.service = service;
        this.baseDeserializer = wrapped;
        this.property = property;
    }

    @Override
    public Object deserialize(final JsonParser p,final DeserializationContext ctxt) throws IOException,JsonProcessingException {
        JsonDeserializer<?> deserializer = baseDeserializer;
        if (deserializer instanceof ContextualDeserializer) {
            deserializer = ((ContextualDeserializer) deserializer).createContextual(ctxt,property);
        }
        return // encryption logic here
    }

    @Override
    public JsonDeserializer<?> createContextual(final DeserializationContext ctxt,final BeanProperty property) throws JsonMappingException {
        JsonDeserializer<Object> wrapped = ctxt.findRootValueDeserializer(property.getType());
        return new EncryptedJsonDeserializer(service,wrapped,property);
    }

解决方法

只需尝试下面的代码,因为您已正确创建了反序列化器,但没有通知spring在反序列化此实体时要在Custom desierializer类下使用。 添加此额外行 @JsonDeserialize(using = EncryptedJsonDeserializer.class) ,然后尝试一次。

@Value
@JsonDeserialize(using = EncryptedJsonDeserializer.class)
public class CardCounterDecreaseRequest {
    @Encrypted
    private final String pinValue;
}

它将为您提供帮助。