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

如何使用log4net在长字符串的序列化JSON中屏蔽敏感值

日志敏感信息屏蔽方案(无需修改调用代码)

针对你在ASP.NET Core项目中遇到的日志脱敏需求,以下是几种无需改动原有调用代码的可行方案:

方案1:基于log4net自定义消息转换器(推荐)

从你使用LogManager.GetLogger的代码来看,项目应该用的是log4net日志框架。我们可以通过自定义消息转换器,在日志输出环节自动替换敏感内容:

步骤1:实现自定义转换器类

public class SensitiveDataMaskingConverter : PatternConverter
{
    protected override void Convert(TextWriter writer, object state)
    {
        var loggingEvent = state as LoggingEvent;
        if (loggingEvent == null)
        {
            base.Convert(writer, state);
            return;
        }

        // 获取原始日志消息
        var rawMessage = loggingEvent.RenderedMessage;
        // 正则匹配JSON格式的pwd字段,替换值为***(忽略大小写)
        var maskedMessage = Regex.Replace(
            rawMessage, 
            @"(""pwd""|pwd):""[^""]+""", 
            "$1:\"***\"", 
            RegexOptions.IgnoreCase
        );

        writer.Write(maskedMessage);
    }
}

步骤2:修改log4net配置文件

在配置中注册转换器,并替换原有消息输出为脱敏后的内容:

<log4net>
  <appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
    <layout type="log4net.Layout.PatternLayout">
      <!-- 注册自定义转换器,命名为mask -->
      <converter>
        <name value="mask" />
        <type value="你的命名空间.SensitiveDataMaskingConverter" />
      </converter>
      <!-- 用%mask替代%message输出脱敏后的日志 -->
      <conversionPattern value="%date [%thread] %-5level %logger - %mask%newline" />
    </layout>
  </appender>
  <!-- 其他appender和root配置保持不变 -->
</log4net>

这个方案只作用于日志输出环节,完全不影响业务代码的序列化逻辑,也不需要修改原有调用代码。

方案2:全局配置JsonConvert脱敏(谨慎使用)

如果希望从序列化源头处理,但要注意此方案会影响所有使用JsonConvert的场景:

步骤1:实现敏感字段转换器

public class SensitiveStringConverter : JsonConverter<string>
{
    // 可扩展需要脱敏的字段列表
    private readonly HashSet<string> _sensitiveFields = new() { "pwd", "password", "secret" };

    public override void WriteJson(JsonWriter writer, string value, JsonSerializer serializer)
    {
        var currentField = writer.Path.Split('.').LastOrDefault();
        if (_sensitiveFields.Contains(currentField?.ToLower()))
        {
            writer.WriteValue("***");
        }
        else
        {
            writer.WriteValue(value);
        }
    }

    public override string ReadJson(JsonReader reader, Type objectType, string existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        return reader.Value?.ToString();
    }
}

步骤2:全局注册转换器

在项目启动时(比如Program.cs)添加:

JsonConvert.DefaultSettings = () => new JsonSerializerSettings
{
    Converters = new List<JsonConverter> { new SensitiveStringConverter() }
};

方案3:基于Microsoft.Extensions.Logging的日志过滤器

如果项目集成了微软原生日志框架,可以通过自定义过滤器拦截并修改日志消息:

步骤1:实现过滤器和包装Logger

public class SensitiveDataMaskingFilter : ILoggerProvider
{
    private readonly ILoggerProvider _innerProvider;

    public SensitiveDataMaskingFilter(ILoggerProvider innerProvider)
    {
        _innerProvider = innerProvider;
    }

    public ILogger CreateLogger(string categoryName)
    {
        var innerLogger = _innerProvider.CreateLogger(categoryName);
        return new MaskingLogger(innerLogger);
    }

    public void Dispose() => _innerProvider.Dispose();

    private class MaskingLogger : ILogger
    {
        private readonly ILogger _innerLogger;

        public MaskingLogger(ILogger innerLogger)
        {
            _innerLogger = innerLogger;
        }

        public IDisposable BeginScope<TState>(TState state) => _innerLogger.BeginScope(state);

        public bool IsEnabled(LogLevel logLevel) => _innerLogger.IsEnabled(logLevel);

        public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
        {
            var originalMsg = formatter(state, exception);
            var maskedMsg = Regex.Replace(
                originalMsg, 
                @"(""pwd""|pwd):""[^""]+""", 
                "$1:\"***\"", 
                RegexOptions.IgnoreCase
            );
            _innerLogger.Log(logLevel, eventId, state, exception, (s, e) => maskedMsg);
        }
    }
}

步骤2:注册过滤器

在Program.cs中添加:

builder.Logging.AddProvider(new SensitiveDataMaskingFilter(new ConsoleLoggerProvider((_, __) => true, true)));

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 19:33:40