Ich habe bestimmte Felder bestimmter Objekte, die, wenn für die Speicherung in DB serialisiert werden, müssen verschlüsselt werden.Java Jackson Custom Polymorphc Deserializer zum Verschlüsseln/Entschlüsseln von Feldern
Sie müssen nicht im Speicher verschlüsselt werden. Ich möchte dies auf transparente Weise für den Rest der Codebasis erreichen, also dachte ich mir, den enc/dec-Schritt auf die ser/deser-Ebene zu setzen.
Um generisch zu sein, ich habe eine Schnittstelle und eine Anmerkung erstellt:
@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 {}
und
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface EncryptedField {}
Die Idee ist, dass die Klassen werden die leere Schnittstelle implementieren, um einen gelegt werden, custom ser/deser, der reflektiv die Felder findet und magisch wirkt, wenn sie kommentiert sind. Die Serialisierung Schritt wirkt wie ein Zauber, und ich erhalte eine Ausgabezeichenfolge wie: {“TYPE ":" Typ1" , "encryptedField": "aGAzLwT47gE/QNlUuAhnJg ==", "unencryptedField": "Klartext"}
Aber die Entschlüsselung ist schrecklich. Ich kann es nicht funktionieren lassen: Ich bin nicht sicher, welche Dinge zu implementieren, um den Polymorphismus UND die Entschlüsselung zu kombinieren.
Wenn ich die @ JsonDeserialize-Annotation entferne und Jackson seine Sache machen lasse, dann deserialisiert es polymorph korrekt, aber mit den verschlüsselten Feldern. Wenn ich versuche, meinen benutzerdefinierten Deserializer zu verwenden, erhalte ich alle möglichen Fehler von NPE bis Jackson. Was ich in meinem Deserializer erreichen will, ist so etwas wie:
- Jackson, dieses Ding deserialisieren, wie Sie wissen, wie die Art Informationen mit den verschlüsselten Feldern
- vor der Rückkehr, lassen Sie mich auf der Instanz meine Entschlüsselung tun (muss nicht richtig eingegeben werden, ich kann durch Reflexion zugreifen). Hier
ist das, was ich bisher:
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;
}
Aber dies nicht mit Fehlern oder über EncryptedDeserializer beschwert hat keinen Standard (kein arg) Konstruktor oder ich habe wirklich verschiedene Möglichkeiten ausprobiert, aber ich erhalte immer stecken.
jackson-crypto auf github tut dies, aber erzeugt ein bisschen anders Ausgabe. Es verwendet Bean-Serialisierungsmodifikatoren, um andere (De-) Serialisierer zu umbrechen. Den Code dafür finden Sie [hier] (https://github.com/meltmedia/jackson-crypto/tree/develop/src/main/java/com/meltmedia/jackson/crypto). –