Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
664 views
in Technique[技术] by (71.8m points)

c# - Editing Log4Net messages before they reach the appenders

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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I had a similar problem, and I solved it by inheriting from ForwardingAppender and then modifying the LoggingEvent (using reflection) before passing it on.

using System.Reflection;
using log4net.Appender;
using log4net.Core;

class MessageModifyingForwardingAppender : ForwardingAppender
{
    private static FieldInfo _loggingEventm_dataFieldInfo;

    public MessageModifyingForwardingAppender()
    {
        _loggingEventm_dataFieldInfo = 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);

        base.Append(loggingEvent);
    }

    /// <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)_loggingEventm_dataFieldInfo.GetValue(loggingEvent);
        loggingEventData.Message = newMessage;
        _loggingEventm_dataFieldInfo.SetValue(loggingEvent, loggingEventData);
    }

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

It's not very pretty, but it works.

Then you need a log4net config that looks something like this

<log4net>
    <appender name="ModifyingAppender" type="Your.Lib.Log4Net.MessageModifyingForwardingAppender,Your.Lib">
        <appender-ref ref="ConsoleAppender" />
    </appender>
    <appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
        <layout type="log4net.Layout.PatternLayout">
            <conversionPattern value="%date %-5level [%thread] %logger: %message%newline"/>
        </layout>
    </appender>
    <root>
        <level value="INFO"/>
        <appender-ref ref="ModifyingAppender"/>
    </root>
</log4net>

and an implementation of GetModifiedMessage() that suits your need, and you are away!


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...