.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 InsightsSerilog.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,可以给原生日志做一层包装,让所有日志输出前都经过脱敏处理:
- 编写自定义日志包装类:
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(); }
- 在
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
相关产品推荐
相关产品推荐

