Editing Log4Net messages before they reach the app

2019-01-28 09:41发布

I have a security tool that sends users their new password through email. The production email module (that I don’t own and don’t want to change) will log the entire html email message body using Log4Net when the threshold is VERBOSE. Since the email contains a domain user’s password in clear text, I would like to remove the password from the log messages before it reaches the appenders.

Is there a way for me to temporary insert an object into the Log4Net stack that would allow me to search the LoggingEvent message and alter it to mask out any passwords that I find? I’d like to insert the object, call the email module, and then remove the object.

7条回答
一夜七次
2楼-- · 2019-01-28 10:11

A small improvement to Chris Priest's solution: inherit your appender not from ForwardingAppender, but from base class AppenderSkeleton. It makes configuration a bit simpler - you don't need to reference other appenders from your one and apply it easily to different loggers now

public class PasswordObfuscationAppender : AppenderSkeleton
{
    private static readonly FieldInfo LoggingEventmDataFieldInfo = typeof(LoggingEvent).GetField(
        "m_data",
        BindingFlags.Instance | BindingFlags.NonPublic);

    protected override void Append(LoggingEvent loggingEvent)
    {
        var originalRenderedMessage = loggingEvent.RenderedMessage;

        var newMessage = GetModifiedMessage(originalRenderedMessage);

        if (originalRenderedMessage != newMessage)
            SetMessageOnLoggingEvent(loggingEvent, newMessage);
    }

    /// <summary>
    /// I couldn't figure out how to 'naturally' change the log message, so use reflection to change the underlying storage of the message data
    /// </summary>
    private static void SetMessageOnLoggingEvent(LoggingEvent loggingEvent, string newMessage)
    {
        var loggingEventData = (LoggingEventData)LoggingEventmDataFieldInfo.GetValue(loggingEvent);
        loggingEventData.Message = newMessage;
        LoggingEventmDataFieldInfo.SetValue(loggingEvent, loggingEventData);
    }

    private static string GetModifiedMessage(string originalMessage)
    {
        // TODO modification implementation
        return originalMessage;
    }
}

usage

<appender name="PasswordObfuscationAppender" type="Foundation.PasswordObfuscationAppender,Foundation" />

<appender name="MainAppender" type="log4net.Appender.RollingFileAppender">
  <file value="..\Logs\File.log" />
</appender>

<root>
  <level value="DEBUG" />
  <appender-ref ref="PasswordObfuscationAppender" />
  <appender-ref ref="MainAppender" />
</root>
查看更多
登录 后发表回答