craterdog.smart.CensorshipSerializer Maven / Gradle / Ivy
/************************************************************************
* Copyright (c) Crater Dog Technologies(TM). All Rights Reserved. *
************************************************************************
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. *
* *
* This code is free software; you can redistribute it and/or modify it *
* under the terms of The MIT License (MIT), as published by the Open *
* Source Initiative. (See http://opensource.org/licenses/MIT) *
************************************************************************/
package craterdog.smart;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import java.io.IOException;
import org.slf4j.ext.XLogger;
import org.slf4j.ext.XLoggerFactory;
/**
* This class handles the masking of sensitive attributes during string serialization. Any string
* attributes that are annotated with the @Sensitive(mask="some pattern")
annotation
* will be masked accordingly.
*
* @author Yan Ma
*/
public class CensorshipSerializer extends JsonSerializer implements ContextualSerializer {
static private final XLogger logger = XLoggerFactory.getXLogger(CensorshipSerializer.class);
private final String mask;
private final char maskingCharacter;
/**
* The default constructor creates a serializer with no mask. None of the characters of the
* string will be masked.
*/
public CensorshipSerializer() {
this.mask = null;
this.maskingCharacter = 'X';
}
/**
* This constructor creates a serializer with the specified mask and masking character. The
* characters of a string serialized using this serializer will be censored using the specified
* mask.
*
* @param mask The pattern to be used to mask the sensitive attribute.
* @param maskingCharacter The character to be used for masking.
*/
public CensorshipSerializer(String mask, char maskingCharacter) {
this.mask = mask;
this.maskingCharacter = maskingCharacter;
}
/*
This is a strange instance method that really probably should be a static method but isn't
due to the ContextualSerializer framework structure. The important thing to realize is that
a default CensorshipSerializer will be created by the framework with the default constructor
and then that instance will be used to create the *real* one with this method below.
*/
@Override
public JsonSerializer> createContextual(SerializerProvider provider, BeanProperty property)
throws JsonMappingException {
Sensitive sensitive = null;
if (property != null) {
logger.debug("Checking property for @Sensitive annotation.");
sensitive = property.getAnnotation(Sensitive.class);
if (sensitive == null) {
logger.debug("Checking property for @Sensitive context annotation.");
sensitive = property.getContextAnnotation(Sensitive.class);
}
}
if (sensitive != null) {
String sensitiveMask = sensitive.mask();
char sensitiveCharacter = sensitive.character();
logger.debug("Found an annotation with mask {} and masking character {}.",
sensitiveMask, sensitiveCharacter);
return new CensorshipSerializer(sensitiveMask, sensitiveCharacter);
}
// the default serializer has no mask so use it
return this;
}
@Override
public void serialize(String value, JsonGenerator generator, SerializerProvider provider)
throws IOException, JsonProcessingException {
if (mask != null) {
Censor censor = new Censor(maskingCharacter);
value = censor.process(value, mask);
}
generator.writeString(value);
}
}