feat(日志管理): 增加 Jackson json 日志脱敏工具类,如果日志入库中有敏感字段则进行删除

(cherry picked from commit a7a5b33c1270e99b01a65307926e98f27c9da3fb)
This commit is contained in:
冷冷 committed 2024-08-16 15:11:45 +08:00
1 parent c80178148a
commit a9b9475fa3
5 files changed
+121 -77

No files matched your search

@@ -33,27 +33,27 @@ import java.util.List;
@ConfigurationProperties(PigxLogProperties.PREFIX)
public class PigxLogProperties {
public static final String PREFIX = "pigx.log";
public static final String PREFIX = "pigx.log";
/**
* 开启日志记录
*/
private boolean enabled = true;
/**
* 开启日志记录
*/
private boolean enabled = true;
/**
* 记录请求报文体
*/
private boolean requestEnabled = true;
/**
* 记录请求报文体
*/
private boolean requestEnabled = true;
/**
* 放行字段,password,mobile,idcard,phone
*/
@Value("${pigx.log.exclude-fields:password,mobile,idcard,phone}")
private List<String> excludeFields;
/**
* 放行字段,password,mobile,idcard,phone
*/
@Value("${pigx.log.exclude-fields:password,mobile,idcard,phone,accessSecret,tokenId,sign}")
private List<String> excludeFields;
/**
* 请求报文最大存储长度
*/
private Integer maxLength = 2000;
/**
* 请求报文最大存储长度
*/
private Integer maxLength = 2000;
}
@@ -18,16 +18,11 @@ package com.pig4cloud.pigx.common.log.event;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.annotation.JsonFilter;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ser.FilterProvider;
import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter;
import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;
import com.pig4cloud.pigx.admin.api.dto.SysLogDTO;
import com.pig4cloud.pigx.admin.api.feign.RemoteLogService;
import com.pig4cloud.pigx.common.core.constant.SecurityConstants;
import com.pig4cloud.pigx.common.core.jackson.PigxJavaTimeModule;
import com.pig4cloud.pigx.common.log.config.PigxLogProperties;
import com.pig4cloud.pigx.common.log.util.JacksonSensitiveFieldUtil;
import jakarta.servlet.ServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
@@ -49,62 +44,50 @@ import java.util.Objects;
@RequiredArgsConstructor
public class SysLogListener implements InitializingBean {
/**
* 忽略序列化的对象类型
*/
private final static Class[] ignoreClass = { ServletRequest.class, BindingResult.class };
/**
* 忽略序列化的对象类型
*/
private final static Class[] ignoreClass = {ServletRequest.class, BindingResult.class};
/**
* new 一个 避免日志脱敏策略影响全局ObjectMapper
*/
private final static ObjectMapper objectMapper = new ObjectMapper();
/**
* new 一个 避免日志脱敏策略影响全局ObjectMapper
*/
private final RemoteLogService remoteLogService;
private final RemoteLogService remoteLogService;
private final PigxLogProperties logProperties;
private final PigxLogProperties logProperties;
@SneakyThrows
@Async
@Order
@EventListener(SysLogEvent.class)
public void saveSysLog(SysLogEvent event) {
SysLogDTO source = (SysLogDTO) event.getSource();
@SneakyThrows
@Async
@Order
@EventListener(SysLogEvent.class)
public void saveSysLog(SysLogEvent event) {
SysLogDTO source = (SysLogDTO) event.getSource();
// json 格式刷参数放在异步中处理,提升性能
if (Objects.nonNull(source.getBody()) && logProperties.isRequestEnabled()) {
Object[] args = (Object[]) source.getBody();
List<Object> list = CollUtil.toList(args);
// 删除部分无法序列化的参数
list.removeIf(obj -> Arrays.stream(ignoreClass).anyMatch(clazz -> clazz.isAssignableFrom(obj.getClass())));
// json 格式刷参数放在异步中处理,提升性能
if (Objects.nonNull(source.getBody()) && logProperties.isRequestEnabled()) {
Object[] args = (Object[]) source.getBody();
List<Object> list = CollUtil.toList(args);
// 删除部分无法序列化的参数
list.removeIf(obj -> Arrays.stream(ignoreClass).anyMatch(clazz -> clazz.isAssignableFrom(obj.getClass())));
try {
// 序列化参数
String params = objectMapper.writeValueAsString(list);
source.setParams(StrUtil.subPre(params, logProperties.getMaxLength()));
}
catch (Exception e) {
log.error("请求参数序列化异常:{}", e.getMessage());
}
}
try {
// 序列化参数
String params = JacksonSensitiveFieldUtil.getObjectMapper().writeValueAsString(list);
source.setParams(StrUtil.subPre(params, logProperties.getMaxLength()));
} catch (Exception e) {
log.error("请求参数序列化异常:{}", e.getMessage());
}
}
source.setBody(null);
remoteLogService.saveLog(source, SecurityConstants.FROM_IN);
}
@Override
public void afterPropertiesSet() {
objectMapper.addMixIn(Object.class, PropertyFilterMixIn.class);
String[] ignorableFieldNames = logProperties.getExcludeFields().toArray(new String[0]);
FilterProvider filters = new SimpleFilterProvider().addFilter("filter properties by name",
SimpleBeanPropertyFilter.serializeAllExcept(ignorableFieldNames));
objectMapper.setFilterProvider(filters);
objectMapper.registerModule(new PigxJavaTimeModule());
}
@JsonFilter("filter properties by name")
class PropertyFilterMixIn {
}
source.setBody(null);
remoteLogService.saveLog(source);
}
@Override
public void afterPropertiesSet() {
String[] ignorableFieldNames = logProperties.getExcludeFields().toArray(new String[0]);
JacksonSensitiveFieldUtil.configureSensitiveFields(ignorableFieldNames);
JacksonSensitiveFieldUtil.registerCustomModule(new PigxJavaTimeModule());
}
}
@@ -0,0 +1,63 @@
package com.pig4cloud.pigx.common.log.util;
import com.fasterxml.jackson.annotation.JsonFilter;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ser.FilterProvider;
import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter;
import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;
import lombok.Getter;
import lombok.SneakyThrows;
/**
* Jackson 脱敏
*
* @author lengleng
* @date 2024/07/18
*/
public class JacksonSensitiveFieldUtil {
@Getter
private static final ObjectMapper objectMapper = new ObjectMapper();
static {
objectMapper.addMixIn(Object.class, PropertyFilterMixIn.class);
}
public static void configureSensitiveFields(String[] ignorableFieldNames) {
FilterProvider filters = new SimpleFilterProvider().addFilter("filter properties by name",
SimpleBeanPropertyFilter.serializeAllExcept(ignorableFieldNames));
objectMapper.setFilterProvider(filters);
}
public static void registerCustomModule(com.fasterxml.jackson.databind.Module module) {
objectMapper.registerModule(module);
}
/**
* string -> object
*
* @param content 内容
* @param valueType 值类型
* @return {@link T }
*/
@SneakyThrows
public static <T> T readValue(String content, Class<T> valueType) {
return objectMapper.readValue(content, valueType);
}
/**
* string -> string
*
* @param content 内容
* @return {@link String }
*/
@SneakyThrows
public static String readStr(String content) {
Object o = objectMapper.readValue(content, Object.class);
return objectMapper.writeValueAsString(o);
}
@JsonFilter("filter properties by name")
private static class PropertyFilterMixIn {
}
}
@@ -23,9 +23,6 @@ import com.pig4cloud.pigx.admin.api.entity.SysLog;
import com.pig4cloud.pigx.common.data.datascope.PigxBaseMapper;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
import java.util.Map;
/**
* <p>
* 日志表 Mapper 接口
@@ -89,6 +89,7 @@ public class SysLogServiceImpl extends ServiceImpl<SysLogMapper, SysLog> impleme
.le(SysLog::getCreateTime, sysLog.getCreateTime()[1]);
}
wrapper.eq(StrUtil.isNotBlank(sysLog.getServiceId()), SysLog::getServiceId, sysLog.getServiceId());
return baseMapper.selectPage(page, wrapper);
}