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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 06:26:01