簡體   English   中英

如何在ASP.NET Web API 2中使用log4net布局模式有條件地捕獲用戶名?

[英]How to conditionally capture user name with log4net layout pattern in ASP.NET web api 2?

我有一個Web api 2應用程序,截至目前已配置Windows身份驗證。 該應用程序具有一個專用的應用程序池,稱為FlowManager,它使用ApplicationPoolIdentity運行。

這是web.config文件中的log4net配置,我在其中使用PatternLayout中的%username記錄用戶名。

<log4net>
    <appender name="LogFileAppender" type="log4net.Appender.RollingFileAppender">
      <param name="File" value="C:\Logs\FlowManager\FlowManager.log" />
      <param name="AppendToFile" value="true" />
      <datePattern value="yyyyMMdd" />
      <rollingStyle value="Size" />
      <maxSizeRollBackups value="3" />
      <maximumFileSize value="2MB" />
      <staticLogFileName value="true" />
      <layout type="log4net.Layout.PatternLayout">
        <param name="ConversionPattern" value="%d{MM-dd-yyyy HH:mm:ss:fff} %-5level [%property{log4net:HostName}, %username] %m%n" />
      </layout>
    </appender>
    <root>
      <level value="TRACE" />
      <appender-ref ref="LogFileAppender" />
    </root>
  </log4net>

所以在我要登錄的應用程序代碼中,我正在使用

logger.Debug("Request entered"); //in a http module

logger.Debug("Test log entry");  //in the api controller

它正在按預期方式生成日志。

2016年6月8日12:06:07:287調試[1178959001DLP, IIS APPPOOL \\ FlowManager ]輸入的請求

2016年6月8日12:06:09:257調試[1178959001DLP, IIS APPPOOL \\ FlowManager ]測試日志條目

現在,要求我記錄經過身份驗證的用戶名。 我發現這個很好的問題是使用log4net捕獲用戶名,並按照說明進行操作並能夠實現。 這是新的log4net配置的樣子。 為了簡單起見,我僅顯示log4net的PatternLayout部分。

<layout type="log4net.Layout.PatternLayout">
        <param name="ConversionPattern" value="%d{MM-dd-yyyy HH:mm:ss:fff} %-5level [%property{log4net:HostName}, %HTTPUser] %m%n" />
        <converter>
          <name value="HTTPUser" />
          <type value="LoggerExtentions.ContextUserPatternConverter" />
        </converter>
      </layout>

如您所見,我創建了一個自定義模式轉換器來捕獲用戶名。

using System.Threading;
using System.Web;
using log4net.Core;
using log4net.Layout.Pattern;

namespace LoggerExtentions
{
    /// <summary>
    /// Log4net custom pattern converter to log context user instaed of app pool user
    /// </summary>
    public class ContextUserPatternConverter : PatternLayoutConverter
    {
        protected override void Convert(System.IO.TextWriter writer, LoggingEvent loggingEvent)
        {
            var userName = string.Empty;
            var context = HttpContext.Current;
            if (context != null && context.User != null && context.User.Identity.IsAuthenticated)
            {
                userName = context.User.Identity.Name;
            }
            else
            {
                var threadPincipal = Thread.CurrentPrincipal;
                if (threadPincipal != null && threadPincipal.Identity.IsAuthenticated)
                {
                    userName = threadPincipal.Identity.Name;
                }
            }
            writer.Write(userName);
        }
    }
}

這給我以下日志消息

06-08-2016 13:06:09:123 DEBUG [1178959001DLP,]請求已輸入

2016年6月8日13:06:09:257調試[1178959001DLP, DOMAIN \\ johnkl ]測試日志條目

如果您發現從http模塊創建的日志條目沒有用戶名,我會得到它,因為尚未使用經過身份驗證的用戶設置上下文。 在這種情況下,我被要求記錄由log4net捕獲的默認用戶名。 我的問題是如何實現? 每當我沒有HttpContext用戶時,如何提供log4net捕獲的默認用戶名? 有沒有辦法在log4net模式布局中提供條件語句? 還是其他替代選項?

看來我能夠找到另一種捕獲它的方法。 由於log4net%username默認為應用程序池標識,因此我將自定義模式轉換器修改為回退為應用程序池標識。

更新:發現loggingEvent參數具有UserName屬性。 我已經修改了代碼以使用該代碼,而不是直接調用System.Security.Principal.WindowsIdentity.GetCurrent()。Name。 LoggingEvent.UserName內部調用相同的方法,但我決定使用loggingEvent.UserName,以防萬一log4net實現將來修改其行為。

public class ContextUserPatternConverter : PatternLayoutConverter
    {
        protected override void Convert(System.IO.TextWriter writer, LoggingEvent loggingEvent)
        {
            var userName = string.Empty;
            var context = HttpContext.Current;
            if (context != null && context.User != null && context.User.Identity.IsAuthenticated)
            {
                userName = context.User.Identity.Name;
            }
            else
            {
                var threadPincipal = Thread.CurrentPrincipal;
                if (threadPincipal != null && threadPincipal.Identity.IsAuthenticated)
                {
                    userName = threadPincipal.Identity.Name;
                }
            }
            if (string.IsNullOrEmpty(userName))
            {
                userName = loggingEvent.UserName;
                //get app pool identity
                //userName = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
            }
            writer.Write(userName);
        }
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM