You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Spring Boot 3中扩展Log4j以拦截日志参数并隐藏敏感数据?

实现方案:自定义Log4j参数转换器完成脱敏

1. 编写自定义脱敏转换器

创建一个继承LogEventPatternConverter的类,作为Log4j的扩展插件,负责识别并处理敏感参数:

import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.config.plugins.Plugin;
import org.apache.logging.log4j.core.pattern.ConverterKeys;
import org.apache.logging.log4j.core.pattern.LogEventPatternConverter;
import org.apache.logging.log4j.core.pattern.PatternConverter;

@Plugin(name = "SensitiveDataConverter", category = PatternConverter.CATEGORY)
@ConverterKeys({"sensitive"})
public class SensitiveDataConverter extends LogEventPatternConverter {

    protected SensitiveDataConverter(String[] options) {
        super("SensitiveData", "sensitive");
    }

    public static SensitiveDataConverter newInstance(String[] options) {
        return new SensitiveDataConverter(options);
    }

    @Override
    public void format(LogEvent event, StringBuilder toAppendTo) {
        Object[] params = event.getMessage().getParameters();
        if (params == null || params.length == 0) {
            toAppendTo.append(event.getMessage().getFormattedMessage());
            return;
        }

        Object[] processedParams = new Object[params.length];
        for (int i = 0; i < params.length; i++) {
            processedParams[i] = maskSensitive(params[i]);
        }

        String format = event.getMessage().getFormat();
        toAppendTo.append(String.format(format, processedParams));
    }

    private Object maskSensitive(Object param) {
        if (param == null) return null;
        String value = param.toString();

        // 手机号脱敏:前3后4保留,中间替换为****
        if (value.matches("1[3-9]\\d{9}")) {
            return value.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2");
        }
        // 身份证脱敏:前6后4保留,中间替换为********
        if (value.matches("\\d{17}[\\dXx]")) {
            return value.replaceAll("(\\d{6})\\d{8}(\\d{4}[\\dXx])", "$1********$2");
        }
        // 密码直接替换为******
        if (value.length() >= 6 || value.contains("password")) { // 可根据实际情况调整判断逻辑
            return "******";
        }
        // 其他敏感规则可在此扩展,比如银行卡号、邮箱等
        return value;
    }
}

2. 修改Log4j配置文件

在项目的log4j2.xml中,将默认的消息输出格式替换为自定义的sensitive转换器:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO">
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <!-- 用%sensitive替代原来的%msg -->
            <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %sensitive%n"/>
        </Console>
    </Appenders>
    <Loggers>
        <Root level="info">
            <AppenderRef ref="Console"/>
        </Root>
    </Loggers>
</Configuration>

3. 测试脱敏效果

写个简单的接口测试日志输出:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestController {
    private static final Logger logger = LoggerFactory.getLogger(TestController.class);

    @GetMapping("/test")
    public String testSensitiveLog() {
        String phone = "13987654321";
        String idCard = "310101198510101234";
        String password = "mySecurePwd123";
        logger.info("用户登录:手机号={}, 身份证={}, 密码={}", phone, idCard, password);
        return "测试完成";
    }
}

启动项目调用接口后,控制台输出的日志会自动脱敏:

2024-05-20 15:10:30.456 [http-nio-8080-exec-1] INFO com.example.demo.TestController - 用户登录:手机号=139****4321, 身份证=310101**1234, 密码=

额外说明

  • 脱敏规则可以根据业务需求自由扩展,比如添加银行卡号\\d{16,19}的脱敏逻辑。
  • 如果需要动态配置脱敏规则,可以把规则定义在application.yml中,通过Spring的配置类注入到转换器里。
  • Spring Boot 3默认集成Log4j 2.x,不需要额外引入依赖,直接使用即可。

内容的提问来源于stack exchange,提问作者Marco

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 13:33:13