Spring Boot 使用 Jackson 注解将敏感信息脱敏

Spring Boot Jackson About 3,630 words

需求

服务端将个人隐私数据进行脱敏。

实现类似@JsonFormat注解,只在返回给前端时脱敏,其他ServiceDAO层不变。

代码

JsonSerializer 序列化器

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 java.io.IOException;
import java.util.Objects;

public class MaskJsonSerializer extends JsonSerializer<String> implements ContextualSerializer {
    private MaskStrategy strategy;

    @Override
    public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        gen.writeString(strategy.mask().apply(value));
    }

    @Override
    public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException {
        Mask annotation = property.getAnnotation(Mask.class);
        if (Objects.nonNull(annotation) && Objects.equals(String.class, property.getType().getRawClass())) {
            this.strategy = annotation.strategy();
            return this;
        }
        return prov.findValueSerializer(property.getType(), property);

    }
}

定义 Mask 注解

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

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)
@JacksonAnnotationsInside
@JsonSerialize(using = MaskJsonSerializer.class)
public @interface Mask {
    
    MaskStrategy strategy();
    
}

定义 MaskStrategy 枚举

import java.util.function.Function;

public enum MaskStrategy {

    USERNAME(s -> s.replaceAll("(\\S)\\S(\\S*)", "$1*$2")),

    ID_CARD(s -> s.replaceAll("(\\d{4})\\d{10}(\\w{4})", "$1**********$2")),

    ID_CARD2(s -> s.replaceAll("(\\d{6})\\w{12}", "$1************")),

    PHONE(s -> s.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2")),

    ADDRESS(s -> s.replaceAll("(\\S{3})\\S{2}(\\S*)\\S{2}", "$1****$2****"));

    private final Function<String, String> mask;

    MaskStrategy(Function<String, String> mask) {
        this.mask = mask;
    }

    public Function<String, String> mask() {
        return mask;
    }
}

使用

@Setter
@Getter
@ToString
public class User {

    @Mask(strategy = MaskStrategy.USERNAME)
    private String username;

    @Mask(strategy = MaskStrategy.USERNAME)
    private String nickname;

    @Mask(strategy = MaskStrategy.PHONE)
    private String phone;

    @Mask(strategy = MaskStrategy.ID_CARD)
    private String idCard;

    @Mask(strategy = MaskStrategy.ID_CARD2)
    private String idCard2;

    @Mask(strategy = MaskStrategy.ADDRESS)
    private String address;

}

测试类

public static void main(String[] args) throws JsonProcessingException {
    User user = new User();
    user.setUsername("张三啊");
    user.setNickname("三三");
    user.setPhone("13333333333");
    user.setIdCard("433333333333433433");
    user.setIdCard2("43333333333343343X");
    user.setAddress("宛平南路600号");

    ObjectMapper objectMapper = new ObjectMapper();
    String json = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(user);
    System.out.println(json);
}

输出

{
  "username" : "张*啊",
  "nickname" : "三*",
  "phone" : "133****3333",
  "idCard" : "4333**********3433",
  "idCard2" : "433333************",
  "address" : "宛平南****0****"
}

备注

Spring Boot项目中直接在返回给前端的类中使用@Mask注解即可。

Views: 210 · Posted: 2024-05-27

————        END        ————

Give me a Star, Thanks:)

https://github.com/fendoudebb/LiteNote

扫描下方二维码关注公众号和小程序↓↓↓

扫描下方二维码关注公众号和小程序↓↓↓
Today On History
Browsing Refresh