如何在Refit API调用日志中屏蔽URL查询参数敏感值
Refit查询参数脱敏解决方案
针对你遇到的URL查询参数(code、secret)日志脱敏需求,提供以下几种实用方案:
方案1:自定义HttpClient委托处理程序(日志专属脱敏)
利用HttpClient的DelegatingHandler拦截请求,在记录日志时对URL中的敏感参数进行替换,不会影响实际请求参数:
public class SensitiveQueryLoggingHandler : DelegatingHandler { private readonly ILogger<SensitiveQueryLoggingHandler> _logger; // 定义需要脱敏的参数名 private readonly List<string> _sensitiveParams = new() { "code", "secret" }; public SensitiveQueryLoggingHandler(ILogger<SensitiveQueryLoggingHandler> logger) { _logger = logger; } protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { // 生成脱敏后的URL用于日志输出 var sanitizedUrl = SanitizeRequestUrl(request.RequestUri); _logger.LogInformation("发起认证请求:{SanitizedUrl}", sanitizedUrl); // 执行原请求逻辑 var response = await base.SendAsync(request, cancellationToken); return response; } private string SanitizeRequestUrl(Uri? uri) { if (uri == null) return string.Empty; var uriBuilder = new UriBuilder(uri); var queryParams = System.Web.HttpUtility.ParseQueryString(uriBuilder.Query); foreach (var param in _sensitiveParams) { if (!string.IsNullOrEmpty(queryParams[param])) { queryParams[param] = "***"; } } uriBuilder.Query = queryParams.ToString(); return uriBuilder.ToString(); } }
注册处理程序
在DI容器中注册Refit客户端时添加该处理程序:
services.AddRefitClient<IAuthServiceRefitApi>() .ConfigureHttpClient(c => c.BaseAddress = new Uri("https://some-url.com/oauth")) .AddHttpMessageHandler<SensitiveQueryLoggingHandler>();
方案2:结构化日志自定义解构策略
如果使用结构化日志(如Serilog),可以通过自定义解构策略,直接对请求对象的敏感字段进行脱敏:
public class GenerateTokenRequestDestructuringPolicy : IDestructuringPolicy { public bool TryDestructure(object value, ILogEventPropertyValueFactory factory, out LogEventPropertyValue result) { if (value is GenerateTokenRequest request) { // 创建脱敏后的匿名对象用于日志 var sanitizedRequest = new { Code = "***", Secret = "***" }; result = factory.CreatePropertyValue(sanitizedRequest, destructureObjects: true); return true; } result = factory.CreatePropertyValue(value); return false; } }
注册解构策略
配置Serilog时添加该策略:
Log.Logger = new LoggerConfiguration() .Destructure.With<GenerateTokenRequestDestructuringPolicy>() // 其他日志配置(如输出目标、级别等) .CreateLogger();
之后在日志中直接记录GenerateTokenRequest对象时,会自动输出脱敏后的内容。
方案3:拆分接口参数并直接脱敏日志
如果请求参数不多,可以直接拆分接口参数,在业务代码中记录日志时手动替换敏感值:
修改Refit接口
public interface IAuthServiceRefitApi { [Post("/token")] Task<GenerateTokenResponse> GenerateTokenAsync( [Query] string code, [Query] string secret, CancellationToken cancellationToken = default); }
业务代码中脱敏日志
public async Task<GenerateTokenResponse> GenerateToken(string code, string secret) { // 日志中直接输出脱敏值 _logger.LogInformation("调用Token接口,code:{Code},secret:{Secret}", "***", "***"); return await _authServiceRefitApi.GenerateTokenAsync(code, secret); }
这种方式简单直接,但参数较多时维护成本较高。
内容的提问来源于stack exchange,提问作者Hakuna
相关产品推荐
相关产品推荐

