自定义注解进行数据脱敏
前言
有些时候,我们可能对输出的某些字段要做特殊的处理在输出到前端,比如:身份证号,电话等信息,在前端展示的时候我们需要进行脱敏处理,这时候通过自定义注解就非常的有用了。在Jackson中要自定义注解,我们可以通过
@JacksonAnnotationsInside
注解来实现,如下示例:
一、自定义注解
importcom.fasterxml.jackson.annotation.JacksonAnnotationsInside;importcom.fasterxml.jackson.databind.annotation.JsonSerialize;importjava.lang.annotation.ElementType;importjava.lang.annotation.Retention;importjava.lang.annotation.RetentionPolicy;importjava.lang.annotation.Target;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
@JsonSerialize(using= SensitiveSerializer.class)public @interfaceSensitive {//加密开始位置 int start()default 0;//加密结束位置 int end() default 0;//加密掩码 String mask() default "*";
}
二、自定义序列化处理器SensitiveSerializer
importcom.fasterxml.jackson.core.JsonGenerator;importcom.fasterxml.jackson.databind.BeanProperty;importcom.fasterxml.jackson.databind.JsonMappingException;importcom.fasterxml.jackson.databind.JsonSerializer;importcom.fasterxml.jackson.databind.SerializerProvider;importcom.fasterxml.jackson.databind.ser.ContextualSerializer;importorg.springframework.util.StringUtils;importjava.io.IOException;importjava.util.Collections;/***@authorsongwp
* @date 2024-11-15
* @desc 自定义序列化器,用于对敏感字段进行脱敏处理*/ public class SensitiveSerializer extends JsonSerializer<String> implementsContextualSerializer {privateSensitive sensitive;
@Overridepublic void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throwsIOException {
String val=value;if (sensitive != null &&StringUtils.hasLength(val)) {
String m=sensitive.mask();int start =sensitive.start();int end =sensitive.end();int totalLength =value.length();if (totalLength <= 2) {
val= totalLength == 1 ? value + m : value.substring(0, 1) +m;
}else if (totalLength <= 6) {
val= value.substring(0, 1) + String.join("", Collections.nCopies(totalLength - 2, m)) + value.substring(totalLength - 1);
}else{int prefixLength = Math.min(start, totalLength - 1);int suffixLength = Math.min(end, totalLength - 1);if (prefixLength >totalLength) {
prefixLength= totalLength / 2;
}if (suffixLength >totalLength) {
suffixLength= totalLength / 2;
}int maskLength = Math.max(0, totalLength - (prefixLength +suffixLength));if (maskLength == 0) {
prefixLength-= 2;
suffixLength-= 2;
maskLength= Math.max(2, totalLength - (prefixLength +suffixLength));
}
prefixLength= Math.min(prefixLength, totalLength - 1);
suffixLength= Math.min(suffixLength, totalLength - 1);
maskLength= totalLength - prefixLength -suffixLength;
val= value.substring(0, prefixLength) + String.join("", Collections.nCopies(maskLength, m)) + value.substring(totalLength -suffixLength);
}
}
gen.writeString(val);
}
@Overridepublic JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) throwsJsonMappingException {
sensitive= property.getAnnotation(Sensitive.class);return this;
}
}
三、在输出的Java Bean中使用上面的注解
importcom.fasterxml.jackson.databind.annotation.JsonSerialize;importcom.fasterxml.jackson.databind.ser.std.ToStringSerializer;importcom.songwp.config.Sensitive;importlombok.AllArgsConstructor;importlombok.Data;importlombok.NoArgsConstructor;importjava.io.Serializable;/***@authorsongwp
*@version1.0
* @date 2024-11-15
* @description: user domain*/@Data
@AllArgsConstructor
@NoArgsConstructorpublic class User implementsSerializable {
@JsonSerialize(using= ToStringSerializer.class)privateLong id;
@Sensitive(start= 2, end = 4)privateString name;
@Sensitive(start= 6, end = 4)privateString idCard;
@Sensitive(start= 4, end = 3)privateString phone;
}
四、在前端展示结果如下:
敏感数据得到了脱敏处理。