问题描述
我正在尝试在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;
}
它将为您提供帮助。