4

I have written @Mask annotation to mask sensitive information in logs. It is working fine when I log data using custom JacksonAnnotationIntrospector with ObjectMapper. I want to use this at logback-spring.xml so that any field annotated with @Mask annotation should be masked in logs. any comments how to do it?

Below are the classes.

Mask.java

package com.mask;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Mask {
    String value() default "XXX-DEFAULT MASK FORMAT-XXX";
}

MaskStringValueSerializer.java

package com.mask;

import com.fasterxml.jackson.core.JsonGenerator;
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 com.fasterxml.jackson.databind.ser.std.StdSerializer;

import java.io.IOException;

public class MaskStringValueSerializer extends StdSerializer<String> implements ContextualSerializer {
    private Mask annot;

    public MaskStringValueSerializer() {
        super(String.class);
    }

    public MaskStringValueSerializer(Mask logMaskAnnotation) {
        super(String.class);
        this.annot = logMaskAnnotation;
    }

    public void serialize(String s, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
        if (annot != null && s != null && !s.isEmpty()) {
            jsonGenerator.writeString(annot.value());
        } else {
            jsonGenerator.writeString(s);
        }
    }

    public JsonSerializer<?> createContextual(SerializerProvider serializerProvider, BeanProperty beanProperty) throws JsonMappingException {
        Mask annot = null;
        if (beanProperty != null) {
            annot = beanProperty.getAnnotation(Mask.class);
        }
        return new MaskStringValueSerializer(annot);

    }
}

MaskAnnotationIntrospector.java

package com.mask;

import com.fasterxml.jackson.databind.introspect.Annotated;
import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector;

public class MaskAnnotationIntrospector extends JacksonAnnotationIntrospector {

    @Override
    public Object findSerializer(Annotated am) {
        Mask annotation = am.getAnnotation(Mask.class);
        if (annotation != null)
            return MaskStringValueSerializer.class;

        return super.findSerializer(am);
    }
}

Model

package com.mask;

import com.fasterxml.jackson.databind.annotation.JsonSerialize;

import java.util.Map;

public class Employee {

    @Mask(value = "*** The value of this attribute is masked for security reason ***")
  //  @JsonSerialize(using = MaskStringValueSerializer.class)
    private String name;

    @Mask
   // @JsonSerialize(using = MaskStringValueSerializer.class)
    private String empId;

    private String company;

    /*@JsonSerialize(using = MaskMapStringValueSerializer.class)
    protected Map<Category, String> categoryMap;*/

    public Employee() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmpId() {
        return empId;
    }

    public void setEmpId(String empId) {
        this.empId = empId;
    }

   /* public Map<Category, String> getCategoryMap() {
        return categoryMap;
    }

    public void setCategoryMap(Map<Category, String> categoryMap) {
        this.categoryMap = categoryMap;
    }*/

    public String getCompany() {
        return company;
    }

    public void setCompany(String company) {
        this.company = company;
    }
}

main class

package com.mask;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;


public class MaskValueTest {
private static Logger logger = LoggerFactory.getLogger(MaskValueTest.class);

    public static void main(String args[]) throws Exception{

        Employee employee = new Employee();

        employee.setName("John Doe");
        employee.setEmpId("1234567890");
        employee.setCompany("Wells");

        ObjectMapper mapper = new ObjectMapper();
        mapper.setAnnotationIntrospector(new MaskAnnotationIntrospector());
        logger.info(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(employee));
    }
}

current output

{ "name" : "*** The value of this attribute is masked for security reason ***", "empId" : "XXX-DEFAULT MASK FORMAT-XXX", "company" : "abc" }

0 Answers0