.NET Core Serilog用户名始终为null [英] .NET Core Serilog username is always null

查看:81
本文介绍了.NET Core Serilog用户名始终为null的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have added this middleware to add usernames to my logging, however, it always appears as null.

这是中间件

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中这样称呼它

I call it in Program.cs and Startup.cs like this

Program.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

Startup.cs

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

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

I noticed that when I hardcoded a property, it would appear in my log under the properties tag. E.g

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>

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

Also, I would like to bring it out of the properties tag and into its own field if possible.

推荐答案

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

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

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

Also, I would like to bring it out of the properties tag and into its own field if possible.

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

The MSSqlServer sink for Serilog by default puts additional properties into the Properties column in its XML format. However, there is a way to configure custom property columns to move certain properties into its own properties. You can configure that using code but since you are using the JSON-based configuration in appsettings.json, you can also do it there.

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

The configuration should look something like this (shortened the configuration here to show only the relevant parts):

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

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

The column is configured as a varchar by default, so it should work for your string value.

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

For properly filling the custom property see the following questions:

  • Serilog Additional Properties (for using Serilog for this in general)
  • Add user to the log context when using Serilog and Asp.Net Core (using ASP.NET Core 1.x but should still give the general idea)

柯克·拉金在聊天中提出了以下建议:

Kirk Larkin suggested the following on chat:

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

From your explanation so far, I'm wondering if you're expecting to see UserName in the message that is being logged as part of the same request that actually signs you in. If you are expecting this, it won't be the case because the LogContext.PushProperty call is happening before your call to something like PasswordSignInAsync (assuming you're using Identity).

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

If this is truly your situation, then you should know that your middleware that sets the custom property is running before any of your controller logic runs. So the custom property is set before the sign-in completed and as such, at the time the middleware ran, an empty username was added as a custom property. So the behavior is perfectly correct. It’s only for subsequent requests that the authentication middleware will be able to authenticate the user before your middleware runs so that you should see the correct username in your logging output.

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

There is not really a good way around this. Of course you could explicitly set the custom property again as you sign the user in. But I would recommend you against that as technically the request was still invoked without any authentication, so it shouldn’t be a problem not to have a username there.

这篇关于.NET Core Serilog用户名始终为null的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆