Lors de la sérialisation avec Jackson et de sa journalisation, je voulais écraser des données sensibles telles que des jetons d'authentification, et je voulais les spécifier facilement avec des annotations, j'ai donc cherché.
Comme ceci, remplacez la propriété par @ Sensitive
dans le champ POOJO par une chaîne appropriée:
@lombok.Value
public class SomeRequest {
/ ** Propriétés qui n'ont pas besoin d'être masquées * /
private final String userId;
/ ** Information sensible * /
@Sensitive
private final String token;
}
Vous avez besoin de trois classes: une implémentation du processus de remplacement, une association avec les annotations pour lesquelles l'implémentation fonctionne et un module qui les enregistre dans ObjectMapper.
Classes qui traitent les champs annotés:
public class SensitiveFieldMaskingSerializer extends StdSerializer<Object> {
private static final long serialVersionUID = 3888199957574169748L;
protected SensitiveFieldMaskingSerializer() {
super(Object.class);
}
@Override
public void serialize(Object value, JsonGenerator gen, SerializerProvider provider) throws IOException {
// Traitement pour remplacer de manière appropriée
if (value instanceof Number) {
gen.writeNumber(0);
} else if (value instanceof String) {
gen.writeString("Hidden: Sensitive string");
} else {
gen.writeNull();
}
}
}
↑ Classe qui associe l'annotation que l'implémentation appelle:
public class SensitiveFieldMaskingAnnotationIntrospector extends NopAnnotationIntrospector {
private static final long serialVersionUID = -4171975975956047379L;
@Override
public Object findSerializer(Annotated am) {
if (am.hasAnnotation(Sensitive.class)) {
return SensitiveFieldMaskingSerializer.class;
}
return null;
}
}
Classe de traitement pour enregistrer ↑ dans ObjectMapper:
static class SensitiveFieldMaskingModule extends Module {
@Override
public String getModuleName() {
return getClass().getSimpleName();
}
@Override
public Version version() {
return Version.unknownVersion();
}
@Override
public void setupModule(SetupContext context) {
context.insertAnnotationIntrospector(new SensitiveFieldMaskingAnnotationIntrospector());
}
}
C'est tout ce dont vous avez besoin pour implémenter, alors utilisons-le:
public final class Main {
public static void main(String[] args) throws Exception {
ObjectMapper logObjectMapper = new ObjectMapper()
.registerModule(new SensitiveFieldMaskingModule());
FooRequest fooRequest = new FooRequest ("Celui que vous pouvez laisser dans le journal", "Celui que vous ne pouvez pas laisser dans le journal");
System.out.println ("résultat de la sérialisation:" + logObjectMapper.writeValueAsString (fooRequest));
// Résultat de la sérialisation: {"userId": "Celui que vous pouvez laisser dans le journal", "token": "Hidden: Sensitive string"}
System.out.println ("Résultat de la conversion en carte:" + logObjectMapper.convertValue (fooRequest, Map.class));
// Converti en résultat de la carte: {userId = Guy que vous pouvez laisser dans le journal, token = Hidden: Chaîne sensible}
}
}
Vous pouvez voir que token
a été remplacé par une autre chaîne dans les deux sorties.
Je l'ai également lié ci-dessus, mais j'ai mis celui qui fonctionne parfaitement.
En passant, lorsque vous avez besoin d'un ObjectMapper différent du normal comme cette fois, vous pouvez éviter des problèmes inutiles en le préparant comme un nouveau journal au lieu d'utiliser l'ObjectMapper utilisé ailleurs. Si vous utilisez un conteneur DI, ne vous inquiétez pas et définissez-le comme un bean nommé.
Recommended Posts