.NET Core Serilog用户名始终为null

时间:2018-12-20 11:09:11

标签: c# asp.net-core serilog

我已经添加了该中间件,以将用户名添加到我的日志记录中,但是,它始终显示为空。

这是中间件

private readonly RequestDelegate next;

    public LogUserName(RequestDelegate next)
    {
        this.next = next;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        LogContext.PushProperty("UserName", context.User.Identity.Name);
        await next(context);
        //return next(context);
    }

我在Program.cs和Startup.cs中这样称呼它

Program.cs

Log.Logger = new LoggerConfiguration()
 .ReadFrom.Configuration(Configuration)
 .Enrich.FromLogContext()
 .Filter.ByExcluding(Matching.FromSource("Microsoft"))
 .Filter.ByExcluding(Matching.FromSource("System"))
 .CreateLogger();

Startup.cs

  app.UseAuthentication();
  app.UseMiddleware<LogUserName>();

我注意到,当我对属性进行硬编码时,该属性将出现在我的日志中的属性标签下。例如

LogContext.PushProperty("UserName", "Test");

<properties><property key='SourceContext'>AAAA.Areas.Identity.Pages.Account.LoginModel</property><property key='ActionId'>e477aa96-f0b5-4790-9253-80fcbc72fbda</property><property key='ActionName'>/Account/Login</property><property key='RequestId'>0HLJ6EBJ4V6PP:00000002</property><property key='RequestPath'>/Identity/Account/Login</property><property key='CorrelationId'></property><property key='ConnectionId'>0HLJ6EBJ4V6PP</property><property key='UserName'>Test</property></properties>

此外,如果可能的话,我想将其带出属性标签并放入其自己的字段中。

1 个答案:

答案 0 :(得分:0)

  

我注意到,当我对属性进行硬编码时,该属性将出现在我的日志中的属性标签下。例如。 LogContext.PushProperty("UserName", "Test")

     
<properties>
    <property key='UserName'>Test</property>
</properties>
     

此外,如果可能的话,我想将其带出属性标签并放入其自己的字段中。

默认情况下,用于Serilog的MSSqlServer接收器将其他属性以其XML格式放入Properties列中。但是,有一种方法可以configure custom property columns将某些属性移到其自己的属性中。您可以使用代码进行配置,但是由于您正在appsettings.json中使用JSON-based configuration,因此您也可以在此处进行配置。

配置应如下所示(此处将配置简化为仅显示相关部分)

"Serilog": {
  "WriteTo": [
    {
      "Name": "MSSqlServer",
      "Args": {
        "connectionString": "…",
        "schemaName": "AnalyticsStudio",
        "tableName": "EventLogs",
        "columnOptionsSection": {
          "additionalColumns": [
            { "ColumnName": "UserName" }
          ]
        }
      }
    }
  ]
}

默认情况下,该列配置为varchar,因此它应适用于您的字符串值。


要正确填充自定义属性,请参见以下问题:


Kirk Larkin在聊天中提出了以下建议:

  

根据目前为止的解释,我想知道您是否希望在实际登录的同一请求的一部分中记录的消息中看到UserName。如果您期望这样做,情况并非如此,因为在调用LogContext.PushProperty之类的电话之前(假设您正在使用Identity)发生了PasswordSignInAsync调用。

如果这确实是您的情况,那么您应该知道设置自定义属性的中间件在任何控制器逻辑运行之前运行。因此,自定义属性是在登录完成之前设置的,因此,在中间件运行时,将空用户名添加为自定义属性。因此,该行为是完全正确的。仅针对后续请求,身份验证中间件将能够在中间件运行之前对用户进行身份验证,以便您应在日志输出中看到正确的用户名。

这实际上不是一个好方法。当然,您可以在登录用户时再次显式设置custom属性。但是我建议您反对这种做法,因为从技术上讲,该请求仍在未经任何身份验证的情况下被调用,因此在此处没有用户名应该不是问题。