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

.NET Core使用Serilog实现日志文件与Application Insights敏感数据脱敏

问题1:.NET Core 中用 Serilog 给日志文件和 Application Insights 脱敏的方法

1. 安装依赖包

通过NuGet安装以下包:

  • Serilog.AspNetCore:Serilog与.NET Core的核心集成包
  • Serilog.Sinks.File:用于将日志输出到文件
  • Serilog.Sinks.ApplicationInsights:用于将日志推送到Application Insights
  • Serilog.Expressions(可选):支持更灵活的文本脱敏过滤

2. 实现自定义脱敏逻辑

最常用的方式是编写自定义解构策略,自动识别敏感字段(如密码、手机号)并替换为***:

public class SensitiveDataDestructuringPolicy : IDestructuringPolicy
{
    // 定义需要脱敏的字段名,忽略大小写
    private readonly HashSet<string> _sensitiveFields = new HashSet<string>
    {
        "Password", "PhoneNumber", "CreditCard", "SSN"
    };

    public bool TryDestructure(object value, ILogEventPropertyValueFactory propertyValueFactory, out LogEventPropertyValue result)
    {
        // 仅处理字典类型的结构化日志属性
        if (value is not IDictionary<string, object> dict)
        {
            result = null;
            return false;
        }

        var sanitizedDict = new Dictionary<string, object>();
        foreach (var kvp in dict)
        {
            if (_sensitiveFields.Contains(kvp.Key, StringComparer.OrdinalIgnoreCase))
            {
                sanitizedDict[kvp.Key] = "***";
            }
            else
            {
                sanitizedDict[kvp.Key] = kvp.Value;
            }
        }

        result = propertyValueFactory.CreatePropertyValue(sanitizedDict);
        return true;
    }
}

3. 配置Serilog并启用脱敏

在Program.cs中配置Serilog,添加文件和Application Insights输出端,同时注册脱敏策略:

var builder = WebApplication.CreateBuilder(args);

// 初始化Serilog
Log.Logger = new LoggerConfiguration()
    .Destructure.With<SensitiveDataDestructuringPolicy>() // 应用脱敏规则
    .WriteTo.File(
        path: "logs/log-.txt",
        rollingInterval: RollingInterval.Day, // 按天滚动日志文件
        formatter: new JsonFormatter() // 与控制台保持一致的JSON格式输出
    )
    .WriteTo.ApplicationInsights(
        builder.Configuration["ApplicationInsights:ConnectionString"], // 从配置文件读取AI连接串
        TelemetryConverter.Traces
    )
    .CreateLogger();

// 让Serilog接管整个应用的日志系统
builder.Host.UseSerilog();

// 后续应用配置...
var app = builder.Build();

如果需要处理日志消息文本中的敏感内容(如直接写在LogInformation("用户手机号:{Phone}")里的内容),可以添加过滤器做正则替换:

.Filter.ByIncludingOnly(evt =>
{
    // 将消息中的11位手机号替换为***
    evt.MessageTemplate = new MessageTemplate(evt.MessageTemplate.Tokens.Select(token =>
    {
        if (token is TextToken textToken)
        {
            var sanitizedText = Regex.Replace(textToken.Text, @"\d{11}", "***");
            return new TextToken(sanitizedText);
        }
        return token;
    }));
    return true;
})

问题2:.NET 6 脱敏在控制台生效,但日志文件未脱敏的解决办法

你当前使用的是原生日志的AddJsonConsole,如果日志文件是通过原生日志的文件输出端实现的,需要确保脱敏逻辑覆盖所有日志输出渠道;若同时混用Serilog和原生日志,也可能导致只有控制台生效。

方案1:统一使用Serilog(推荐)

如果你的脱敏逻辑是基于Serilog实现的,直接将日志文件输出切换为Serilog的File Sink,同时通过builder.Host.UseSerilog()让Serilog接管所有日志,这样脱敏规则会自动应用到文件和Application Insights输出,与控制台保持一致。

方案2:给原生日志添加全局脱敏

若不想切换到Serilog,可以给原生日志做一层包装,让所有日志输出前都经过脱敏处理:

  1. 编写自定义日志包装类:
public class SanitizingLogger : ILogger
{
    private readonly ILogger _innerLogger;
    private readonly HashSet<string> _sensitiveFields = new HashSet<string> { "Password", "PhoneNumber" };

    public SanitizingLogger(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)
    {
        // 处理结构化日志中的敏感字段
        if (state is IEnumerable<KeyValuePair<string, object>> properties)
        {
            var sanitizedProperties = properties.ToDictionary(
                kvp => kvp.Key,
                kvp => _sensitiveFields.Contains(kvp.Key, StringComparer.OrdinalIgnoreCase) ? "***" : kvp.Value
            );
            _innerLogger.Log(logLevel, eventId, sanitizedProperties, exception, formatter);
            return;
        }
        _innerLogger.Log(logLevel, eventId, state, exception, formatter);
    }
}

public class SanitizingLoggerProvider : ILoggerProvider
{
    private readonly ILoggerProvider _innerProvider;

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

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

    public void Dispose() => _innerProvider.Dispose();
}
  1. 在Program.cs中注册包装器,替换原生的文件日志提供器:
builder.Logging.AddJsonConsole(options => options.JsonWriterOptions = new JsonWriterOptions
{
    Indented = true
});

// 先安装Microsoft.Extensions.Logging.File包,再添加带脱敏的文件日志
builder.Logging.AddProvider(new SanitizingLoggerProvider(
    new FileLoggerProvider(new FileLoggerOptions
    {
        Path = "logs/log-.txt",
        RollingInterval = RollingInterval.Day
    })
));

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 13:58:16