
- 背景
在项目的开发中,经常会把第三方接口的返回值以json字符串的形式打印到日志中方便出现问题后进行定位,但是在一些项目中会有一些敏感的信息不能打印到日志中,需要进行匿名化的处理,下面介绍两种常见的实现方式 - 方案一
直接在需要匿名化的字段上使用 @JsonSerialize(using = AnonymizeJsonSerializer.class)注解的形式-实现和下面一样,由AnonymizeJsonSerializer来实现序列化- 优点
1、对所有的ObjectMapper有效
2、容易理解、方便使用 - 缺点:如果转换为json之后的对象在后面提交给第三方的时候还需要使用的话就会出现传递给第三方的值被序列化了
- 优点
- 方案二
重新定义一个ObjectMapper,在ObjectMapper中注入支持匿名化的module,在module中实现匿名化的逻辑,- 优点:匿名化的打印逻辑相对独立,不影响其他调用的正常实现
- 缺点:实现优点麻烦,不太容易理解
- 实现代码如下
package com.hkk.demo.utils;
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.BeanDescription;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.Module;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationConfig;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.BeanPropertyWriter;
import com.fasterxml.jackson.databind.ser.BeanSerializerModifier;
import com.fasterxml.jackson.databind.type.MapType;
import com.google.common.collect.Lists;
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;
import lombok.Data;
import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
@Slf4j
@UtilityClass
public class AnonymizeJsonUtil {
private static final String EMPTY_JSON = "{}";
// 字段名称包含这些字段的需要匿名化
private static final List ANONYMIZE_NAMES = Lists.newArrayList("cash");
public static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
static {
// 反序列化时忽略不存在的字段
OBJECT_MAPPER.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
// 注册处理敏感字段的扩展模块
OBJECT_MAPPER.registerModule(new AnonymizeModule());
}
public static String toJsonString(Object object) throws JsonProcessingException {
return OBJECT_MAPPER.writevalueAsString(object);
}
public static String toJsonStringOrEmpty(Object object) {
try {
return toJsonString(object);
} catch (JsonProcessingException e) {
log.error("json to string error", e);
}
return EMPTY_JSON;
}
private static class AnonymizeModule extends Module {
private static final String MODULE_NAME = "jackson-anonymize-module";
private final Version version = VersionUtil.parseVersion("0.0.1", "com.hkk", MODULE_NAME);
@Override
public String getModuleName() {
return MODULE_NAME;
}
@Override
public Version version() {
return version;
}
@Override
public void setupModule(SetupContext setupContext) {
setupContext.addBeanSerializerModifier(new FieldAnonymizeModifier());
}
public static class FieldAnonymizeModifier extends BeanSerializerModifier {
@Override
public List changeProperties(SerializationConfig config,
BeanDescription beanDesc, List beanProperties) {
beanProperties = super.changeProperties(config, beanDesc, beanProperties);
List newWriters = new ArrayList<>();
for (BeanPropertyWriter writer : beanProperties) {
if (needAnonymize(writer)) {
// 如果带有 @Sensitive 注解,并且是字符串,则使用自定义处理
JsonSerializer 欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)