Фильтр для logger на c#

Вопрос заключается в том, что в рамках устранения Log Forgin типа XSS уязвимости необходимо все сообщения типа string, которые падают в _logger.Information(string message) предварительно до отправки прогонять через функцию очистки. Каким образом это можно организовать в общем для всех используемых логгеров в приложении на уровне общей логики ибо оборачивать message в каждом логгере - это будет страх и ужас. Само сообщение компанутеся из строк и взодных параметров эндпоинтов. То есть вопрос, как строку, положенную в логгер, до логгирования прогнать через другой метод?


Ответы (1 шт):

Автор решения: Alexander Petrov

Для решения вашей задачи достаточно реализовать собственный форматтер логирования.
Console log formatting
Я взял пример из документации и лишь слегка изменил.

public sealed class CustomFormatter : ConsoleFormatter, IDisposable
{
    private readonly IDisposable _optionsReloadToken;
    private CustomOptions _formatterOptions;

    public CustomFormatter(IOptionsMonitor<CustomOptions> options)
        // Case insensitive
        : base("customName") =>
        (_optionsReloadToken, _formatterOptions) =
            (options.OnChange(ReloadLoggerOptions), options.CurrentValue);

    private void ReloadLoggerOptions(CustomOptions options) =>
        _formatterOptions = options;

    public override void Write<TState>(
        in LogEntry<TState> logEntry,
        IExternalScopeProvider scopeProvider,
        TextWriter textWriter)
    {
        string? message =
            logEntry.Formatter?.Invoke(logEntry.State, logEntry.Exception);

        if (message is null)
        {
            return;
        }

        message = Filter(message, _formatterOptions);
        textWriter.WriteLine(message);
    }

    private string Filter(string message, CustomOptions _formatterOptions)
    {
        return message.Replace(_formatterOptions.OldValue, _formatterOptions.NewValue);
    }

    public void Dispose() => _optionsReloadToken?.Dispose();
}

Очистка происходит в методе Filter. Реализуйте там свою логику.

Так выглядит класс с настройками:

public class CustomOptions : ConsoleFormatterOptions
{
    public string? OldValue { get; set; }
    public string? NewValue { get; set; }
}

Метод расширения

public static class ConsoleLoggerExtensions
{
    public static ILoggingBuilder AddCustomFormatter(
        this ILoggingBuilder builder,
        Action<CustomOptions> configure) =>
        builder
            .AddConsole(options => options.FormatterName = "customName")
            .AddConsoleFormatter<CustomFormatter, CustomOptions>(configure);
}

Регистрируем наш форматтер. Код может различаться в зависимости хоста.

builder.Services.AddLogging(builder =>
    builder.AddCustomFormatter(options =>
    {
        options.OldValue = "#";
        options.NewValue = "";
    }));

В итоге сообщение #Hello# превращается в Hello.


При желании можно создать собственные провайдер и логгер.
Implement a custom logging provider in .NET
Это даст больше возможностей, но сложнее в реализации.

→ Ссылка