使用jackson进行json序列化时进行敏感字段脱敏(加密)或者忽略
需求:
1、通过注解的方式指定字段在序列化时进行脱敏或者加密;
2、通过注解的方式指定字段在序列化时忽略掉;
3、某些情况下需要处理的类不是我们可以修改的,但是也要实现上述两项需求;
实现如下:
工具类SensitiveJsonUtil:
package com.example.jackson;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
public class SensitiveJsonUtil {
private static ObjectMapper objectMapper = new ObjectMapper();
static {
// 反序列化时忽略不存在的字段
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
// 注册处理敏感字段的扩展模块
objectMapper.registerModule(new SensitiveFieldProcessModule());
// 通过mixIn功能来按字段名忽略一些字段
objectMapper.addMixIn(Object.class, IgnoreSensitiveFieldsMixin.class);
}
@JsonIgnoreProperties(
value = {
"password",
"secret",
"token"
}
)
static class IgnoreSensitiveFieldsMixin {
}
public static String toJsonString(Object object) {
try {
return objectMapper.writeValueAsString(object);
} catch (JsonProcessingException e) {
throw new RuntimeException(String.format("toJsonString error, %s", e.getMessage()), e);
}
}
}
扩展模块类SensitiveFieldProcessModule(这里仅为demo,所以一些相关的类直接以嵌套类放在了一起)
package com.example.jackson;
import com.fasterxml.jackson.annotation.JacksonAnnotation;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.Version;
import com.fasterxml.jackson.core.util.VersionUtil;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.ser.BeanPropertyWriter;
import com.fasterxml.jackson.databind.ser.BeanSerializerModifier;
import com.fasterxml.jackson.databind.type.MapType;
import org.apache.commons.lang3.StringUtils;
import java.io.IOException;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.ArrayList;
import java.util.List;
public class SensitiveFieldProcessModule extends Module {
private static final String MODULE_NAME = "jackson-sensitive-field-process-module";
private Version version = VersionUtil.parseVersion("0.0.1", "com.example", MODULE_NAME);
@Override
public String getModuleName() {
return MODULE_NAME;
}
@Override
public Version version() {
return version;
}
@Override
public void setupModule(SetupContext setupContext) {
setupContext.addBeanSerializerModifier(new SensitiveFieldModifier());
}
public static class SensitiveFieldModifier extends BeanSerializerModifier {
@Override
public List<BeanPropertyWriter> changeProperties(SerializationConfig config, BeanDescription beanDesc, List<BeanPropertyWriter> beanProperties) {
List<BeanPropertyWriter> newWriters = new ArrayList<>();
for (BeanPropertyWriter writer : beanProperties) {
if (writer.getAnnotation(Sensitive.class) != null && writer.getType().isTypeOrSubTypeOf(String.class)) {
// 如果带有 @Sensitive 注解,并且是字符串,则使用自定义处理
JsonSerializer<Object> serializer = new SensitiveJsonSerializer(writer.getSerializer());
writer.assignSerializer(serializer);
}
newWriters.add(writer);
}
return newWriters;
// super.changeProperties(config, beanDesc, beanProperties);
}
@Override
public JsonSerializer<?> modifyMapSerializer(SerializationConfig config, MapType valueType, BeanDescription beanDesc, JsonSerializer<?> serializer) {
return super.modifyMapSerializer(config, valueType, beanDesc, serializer);
}
}
@JacksonAnnotation
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface Sensitive {
}
public static class SensitiveJsonSerializer extends JsonSerializer<Object> {
private final JsonSerializer<Object> serializer;
public SensitiveJsonSerializer(JsonSerializer<Object> serializer) {
this.serializer = serializer;
}
@Override
public void serialize(Object object, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException, JsonProcessingException {
if (object != null && object instanceof String) {
String str = (String) object;
if (StringUtils.isNotBlank(str)) {
object = processSensitiveField(str);
}
}
if (this.serializer == null) {
serializerProvider.defaultSerializeValue(object, jsonGenerator);
} else {
this.serializer.serialize(object, jsonGenerator, serializerProvider);
}
}
private static String processSensitiveField(String input) {
if (StringUtils.isBlank(input)) {
return input;
}
input = StringUtils.trim(input);
int strLen = input.length();
if (strLen <= 1) {
return "*";
} else if (strLen == 2) {
return String.format("%s*", input.charAt(0));
} else if (strLen == 3) {
return String.format("%s*%s", input.charAt(0), input.charAt(strLen - 1));
} else {
int left = strLen / 4;
int right = strLen / 3;
return String.format("%s%s%s",
StringUtils.left(input, left),
StringUtils.repeat('*', (strLen - left - right)),
StringUtils.right(input, right));
}
}
}
}
使用示例:
package com.example;
import com.example.jackson.SensitiveFieldProcessModule;
import com.example.jackson.SensitiveJsonUtil;
import java.util.HashMap;
import java.util.Map;
public class App {
public static void main(String[] args) {
Person person = new Person();
person.setUsername("张一二");
person.setIdNumber("1000000000112245");
person.setPassword("123456(password)");
Map<String, String> otherInfo = new HashMap<>();
otherInfo.put("nation", "CN");
otherInfo.put("secret", "(secret)");
person.setOtherInfo(otherInfo);
System.out.println(SensitiveJsonUtil.toJsonString(person));
// 输出:{"username":"张一二","idNumber":"1000*******12245","otherInfo":{"nation":"CN"}}
}
static class Person {
private String username;
@SensitiveFieldProcessModule.Sensitive
private String idNumber;
private String password;
private Map<String, String> otherInfo;
// ... 省略getter/setter
}
}
参考文档:
本博客(liqipeng)除非已明确说明转载,否则皆为liqipeng原创或者整理,转载请保留此链接:https://www.cnblogs.com/liqipeng/p/15448825.html。
本博客(liqipeng)除非已明确说明转载,否则皆为liqipeng原创或者整理,转载请保留此链接:https://www.cnblogs.com/liqipeng/p/15448825.html。
如果你觉得这篇文章对你有帮助或者使你有所启发,请点击右下角的推荐按钮,谢谢,:)