[Frühling] Verschleiern Sie bestimmte Felder mit Anmerkungen [Java]

Wenn Sie die ID verwenden, die in der Datenbank automatisch nummeriert wird, wie für die auf dem Bildschirm angezeigte ID, wird der Benutzer verschiedene Dinge erraten. (Es wird die Anzahl der Benutzer genannt)

Für solch ein spezielles Feld denke ich, dass es üblich ist, ein dediziertes Wertobjekt vorzubereiten und den Prozess der ID-Konvertierung intern zu schreiben. Wenn jedoch der Typ des Anforderungs- oder Antwortmodells aufgrund komplizierter Umstände nicht geändert werden kann, habe ich untersucht, ob es mit Anmerkungen verwaltet werden kann.

Die Arbeitsumgebung ist "Java9", "SpringBoot (2.0.0.RELEASE)". (Ich habe nichts Besonderes gemacht, daher denke ich, dass andere Versionen in Ordnung sind.)

Bedarf

Die Anforderungen für diese Zeit sind wie folgt.

Spezifikation

Basierend auf den oben genannten Anforderungen möchte ich die Spezifikationen wie folgt vornehmen.

Implementierung

Serializer

Diese Klasse ist verschleiert. (Wo soll der Server verlassen werden) Erben und implementieren Sie "StdSerializer". Wenn es "null" ist, endet es so wie es ist. (Weil NotNull usw. durch andere Anmerkungen ausgedrückt werden sollte)

ObfuscateSerializer.java


public class ObfuscateSerializer extends StdSerializer<Long> {

    private static final long serialVersionUID = -6910413385029615313L;

    protected ObfuscateSerializer() {
        super(Long.class);
    }

    @Override
    public void serialize(Long value, JsonGenerator gen, SerializerProvider provider) throws IOException {
        //Verschleierungslogik
        if (value == null) {
            return;
        }
        gen.writeNumber(value + 1);
    }
    
}

Deserializer

Dies ist eine Klasse, die vereinfacht. (Beim Betreten des Servers) Wie der Serializer verwendet er "StdDeserializer".

ObfuscateDeserializer.java


public class ObfuscateDeserializer extends StdDeserializer<Long> {

    private static final long serialVersionUID = 4303388430635458159L;

    protected ObfuscateDeserializer() {
        super(Long.class);
    }

    @Override
    public Long deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        //Vereinfachte Logik
        return Long.parseLong(p.getValueAsString()) - 1;
    }

}
{
"timestamp": 1521424385168,
"status": 400,
"error": "Bad Request",
"message": "JSON parse error: For input string: \"hoge\"; nested exception is com.fasterxml.jackson.databind.JsonMappingException: For input string: \"hoge\" (through reference chain: com.example.Hoge[\"value\"])",
"path": "/api/sample/obfuscate"
}

Anmerkung

Da es sich um eine Markierungsanmerkung handelt, hat sie keine Eigenschaften. Das Ziel wird in den Spezifikationen nur auf "ElementType.FIELD" gesetzt.

Obfuscate.java


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

Annotation Interceptor

Es ist eine Klasse, die die definierte Annotation dem Serializer / Deserializer zuordnet. Erben und implementieren Sie "JacksonAnnotationIntrospector". Diese Klasse wird für jedes Element aufgerufen, wenn Jackson in Spring Boot json in die angegebene Klasse konvertiert, wenn die Zielklasse, das Feld oder die Methode mit Anmerkungen versehen ist. Dieses Mal werden wir den Serializer und Deserializer einzigartig machen, also werden wir den "findSerializer" und den "findDeserializer" überschreiben.

MyAnnotationInterceptor.java


public class MyAnnotationInterceptor extends JacksonAnnotationIntrospector {

    private static final long serialVersionUID = -7722925738908936096L;

    @Override
    public Object findSerializer(Annotated a) {
        if (a.hasAnnotation(Obfuscate.class)) {
            return ObfuscateSerializer.class;
        }
        return super.findSerializer(a);
    }

    @Override
    public Object findDeserializer(Annotated a) {
        if (a.hasAnnotation(Obfuscate.class)) {
            return ObfuscateDeserializer.class;
        }
        return super.findDeserializer(a);
    }

}

Konfig

Registrieren Sie den obigen Annotation Interceptor bei Spring Boot.

JacksonConfig.java


@Configuration
public class JacksonConfig {

    @Bean
    public Jackson2ObjectMapperBuilder jacksonBuilder() {
        Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
        builder.annotationIntrospector(new MyAnnotationInterceptor());
        return builder;
    }

}

Anwendungsbeispiel

Jetzt, da Sie bereit sind, können Sie den Feldern des Anforderungs- oder Antwortmodells "@ Obfuscate" hinzufügen, und sie werden automatisch konvertiert.

ObfuscateRequest.java


@lombok.Value
public class ObfuscateRequest {
    
    @Obfuscate
    Long id;

}

Zusammenfassung

Dieses Mal habe ich eine Anmerkung definiert, um das Feld zu verschleiern und zu vereinfachen. Ich denke, es gibt Situationen, in denen es nützlich ist, wenn es bereits veröffentlicht wurde und es schwierig ist, die Klasse zu ändern, oder wenn das Modell wiederverwendet wird und es nicht geändert werden kann. Auch bei Wertobjekten gibt es einige Unannehmlichkeiten (obwohl dies vermieden werden kann), wie z. B. die Vertiefung der Hierarchie bei der Verwendung von json. Daher hielt ich dies für eine gute Wahl.

Referenz

https://qiita.com/nijuya_o/items/0f512792c4db27913c7a https://qiita.com/k_ui/items/b6e1763d023da96ea46f

Recommended Posts

[Frühling] Verschleiern Sie bestimmte Felder mit Anmerkungen [Java]
Verwenden von Mapper mit Java (Spring)
Frühling Java
Spring Dependency Injection mit Java, Kotlin
[Java] Spring DI ③
Sortieren mit Java-Komparator
Schrottpraxis mit Java ②
Schrottpraxis mit Java ①
Überprüfen Sie jetzt die Java-Anmerkungen
Versuchen Sie es mit Spring JDBC