【问题标题】:.net core 2.2, Reading setting from user secrets for serilog.net core 2.2,从用户机密中读取 serilog 的设置
【发布时间】:2019-05-21 11:01:09
【问题描述】:

我已经设置了我的解决方案,serilog 从 appsettings.json 读取值

public void Configure(IApplicationBuilder application, IHostingEnvironment environment, ILoggerFactory loggerFactory)
{
     Logger log = new LoggerConfiguration()
            .ReadFrom.Configuration(Configuration)
            .CreateLogger();
     loggerFactory.AddSerilog(log);

应用设置如下所示:

 "Serilog": {
    "Using": [ "Serilog.Sinks.Slack", "Serilog.Sinks.ApplicationInsights" ],
    "MinimumLevel": {
      "Default": "Debug",
      "Override": {
        "Microsoft": "Error",
        "System": "Error"
      }

    },
    "WriteTo": [
      {
        "Name": "Slack",
        "Args": {
          "WebHookUrl": "https://hooks.slack.com/services/xxx/yyy/zzz",
          "CustomChannel": "#channel"
        }
      },
      {
        "Name": "ApplicationInsights",
        "Args": {
          "InstrumentationKey": "xxx-xxx-xxx-xxx-xxx",
          "restrictedToMinimumLevel": "Information",
          "telemetryConverter": "Serilog.Sinks.ApplicationInsights.Sinks.ApplicationInsights.TelemetryConverters.TraceTelemetryConverter, Serilog.Sinks.ApplicationInsights"
        }
      }
    ]
  }

所以到这里为止一切都很好,但我不想在我的存储库中存储 webhook 和 InstrumentationKey 之类的秘密。我想从安全的地方阅读它们,例如开发环境中的用户机密和生产中的 Key-vault。如何更改它以替换 usersecrets 中的值?

https://docs.microsoft.com/en-us/aspnet/core/security/app-secrets?view=aspnetcore-2.2&tabs=windows

反正配置会自动被覆盖吗?

如果没有,我知道我可以从秘密中读取我的配置,比如说

  webHookUrl = Configuration["Serilog:WriteTo:Slack:WebHookUrl"];

但是我该如何在 loggerConfig 上应用它呢?我的意思是,writeTo 部分从设置中是动态的,然后我应该将它添加到代码中吗? :\

更新

由于很多人都问过,在我的program.cs中我有:

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .UseApplicationInsights()
                .UseStartup<Startup>();

根据 Microsoft 文档,一切正常,因为我有 CreateDefaultBuilder 并且我正在运行 .net core 2.2。 https://docs.microsoft.com/en-us/aspnet/core/security/app-secrets?view=aspnetcore-2.2&tabs=windows#access-a-secret

在 ASP.NET Core 2.0 或更高版本中,在开发模式下,当项目调用 CreateDefaultBuilder 以使用预配置的默认值初始化主机的新实例时,会自动添加用户机密配置源。当 EnvironmentName 为 Development 时,CreateDefaultBuilder 调用 AddUserSecrets。

当未调用 CreateDefaultBuilder 时,通过在 Startup 构造函数中调用 AddUserSecrets 显式添加用户机密配置源。仅当应用在开发环境中运行时才调用 AddUserSecrets

【问题讨论】:

  • 关于 .Net Core 配置的一点是,设置来自哪里并不重要,只要其中一个提供者提取了一个设置,它通常可以用于配置。您可以将 serilog 设置放在任何提供程序中,例如 keyvault 提供程序、环境变量等。如果您在 Azure 应用服务中,我建议使用该服务的应用程序设置。
  • @Crowcoder 感谢您的回复。我已经在我的秘密中复制了完全相同的设置并将其从我的 appsettings 中删除,但现在我没有收到任何日志。我错过了什么吗?
  • 如何设置配置生成器?你在用builder.AddUserSecrets&lt;Startup&gt;();吗?
  • @ESG 不,因为我在 .net core 2.2 上,所以我应该可以使用 WebHost.CreateDefaultBuilder(args)。我不应该吗?
  • @AshkanSirous 不,机密仅按需加载(通常仅在开发环境中)

标签: c# asp.net-core serilog asp.net-core-2.2


【解决方案1】:

这是我目前用于 ASP.NET Core 3.1 Web 应用程序的内容。它支持appsettings.json(适用于所有环境)和 Visual Studio 的用户密码 (secrets.json),无需在代码中写入任何有意义的信息(例如用户密码的唯一 ID)。

Program.cs 文件的Main() 方法:

public static void Main(string[] args)
{
    var configuration = new ConfigurationBuilder()
        .SetBasePath(Directory.GetCurrentDirectory())
        .AddJsonFile("appsettings.json",
            optional: false,
            reloadOnChange: true)
        .AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production"}.json", 
            optional: true,
            reloadOnChange: true)
        .AddUserSecrets<Startup>(optional: true, reloadOnChange: true)
        .Build();

    Log.Logger = new LoggerConfiguration()
        .WriteTo.MariaDB(
            restrictedToMinimumLevel: Serilog.Events.LogEventLevel.Information,
            connectionString: configuration.GetConnectionString("DefaultConnection"),
            tableName: "Logs",
            autoCreateTable: false,
            useBulkInsert: false,
            options: new MariaDBSinkOptions() 
            { 
                LogRecordsExpiration = new TimeSpan(90, 0, 0, 0, 0) 
            })
        .CreateLogger();

    try
    {
        Log.Information("Starting the HostBuilder...");
        CreateWebHostBuilder(args).Build().Run();
    }
    catch (Exception ex)
    {
        Log.Fatal(ex, "The HostBuilder terminated unexpectedly");
    }
    finally
    {
        Log.CloseAndFlush();
    }
}

Program.cs 文件的CreateWebHostBuilder() 方法:

public static IHostBuilder CreateWebHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.ConfigureKestrel(serverOptions =>
            {
                // Set properties and call methods on options
            })
            .UseStartup<Startup>();
        })
        .UseSerilog();

如果您需要更多信息,请查看我博客上的 this post

【讨论】:

  • 代码在非开发环境中运行时AddUserSecrets行会出现问题吗?
  • 没问题,只要将optional设置为true即可。
【解决方案2】:

我已在我的秘密中复制了完全相同的设置并将其从我的 appsettings 中删除,但现在我没有收到任何日志。我错过了什么吗?

如果您将 serilog 配置从 appsettings.json 移动到 secrets.json,则需要修改 Configure 中的 ReadFrom.Configuration() 以从 secrets.json 中读取。

var configuration = new ConfigurationBuilder()
          .AddJsonFile("C:\\Users\\Administrator\\AppData\\Roaming\\Microsoft\\UserSecrets\\aspnet-SerilogCore\\secrets.json")
          .Build();//Replace above with path of your secrets.json

Logger log = new LoggerConfiguration()
            .ReadFrom.Configuration(configuration)
            .CreateLogger();
loggerFactory.AddSerilog(log);

【讨论】:

  • 您可以通过以下方式使用.AddUserSecrets() 方法,而不是以明文形式添加secrets.json 完整路径(这不是很好):.AddUserSecrets(&lt;Startup&gt;(optional: true, reloadOnChange: true)。我添加了一个专门的答案来更好地解释它。
【解决方案3】:

我相信@Crowcoder 在他对 OP 的第一条评论中是正确的。因此,您需要做的是将 appsettings.json 中的结构和部分配置“复制”到主目录中的 secrets.json 文件中

所以在你的情况下,你会做这样的事情:

    "Serilog": {

    "WriteTo": [
      {
        "Name": "Slack",
        "Args": {
          "WebHookUrl": "https://hooks.slack.com/services/xxx/yyy/zzz"
        }
      },
      {
        "Name": "ApplicationInsights",
        "Args": {
          "InstrumentationKey": "xxx-xxx-xxx-xxx-xxx"
        }
      }
    ]
  }

因此只有秘密信息存在。

【讨论】:

    【解决方案4】:

    此答案专门针对“如何使用 Serilog 使用用户密码?”。

    用户机密 json 必须反映 Serilog 部分中的 json 结构。如果您定义了 2 个 Serilog 接收器,但只有一个用户密码,则用户密码 json 仍然需要包含两个接收器(有点 - 参见下面的示例)。

    为什么? User Secrects 必须与 Serilog 配置中“WriteTo”数组的序号索引匹配。请参阅以下基于 OP 的 Serilog json 的示例。

    注意不需要包含 WriteTo[idx].Name 值,但包含它是为了更容易阅读用户机密。请记住,User Secrets 不使用 sink 的名称,而是匹配 Serilog WriteTo 数组中基于索引的定义;您不需要在 User Secrets 中包含 WriteTo[idx].Name 键/值。但是,如果这样做,请确保名称与实际接收器的名称完全匹配,否则它将覆盖配置值。

    用户机密 JSON 示例

    两个接收器/WriteTo 都有用户密码

    {
      "SomeOtherConfig": {
        "key": "value"
      },
      "Serilog": {
        "WriteTo": [
          {
            "Name": "Slack",
            "Args": {
              "WebHookUrl": "https://hooks.slack.com/services/my/secret/url",
            }
          },
          {
            "Name": "ApplicationInsights",
            "Args": {
              "InstrumentationKey": "my-secret-instrumentation-key"
            }
          }
        ]
      }
    }
    

    只有第一个 sinks/WriteTo 有 User Secrets

    由于用户密码将匹配WriteTo 数组的索引,因此只需包含第一个带有用户密码的接收器。

    {
      "SomeOtherConfig": {
        "key": "value"
      },
      "Serilog": {
        "WriteTo": [
          {
            "Name": "Slack",
            "Args": {
              "WebHookUrl": "https://hooks.slack.com/services/my/secret/url",
            }
          }
        ]
      }
    }
    

    只有最后一个 sinks/WriteTo 有 User Secrets

    由于用户密码将匹配WriteTo 数组的索引,因此第一个接收器占位符必须包含用户密码,并且需要包含与用户密码的第二个同步。

    {
      "SomeOtherConfig": {
        "key": "value"
      },
      "Serilog": {
        "WriteTo": [
          {
            "Name": "Slack",
          },
          {
            "Name": "ApplicationInsights",
            "Args": {
              "InstrumentationKey": "my-secret-instrumentation-key"
            }
          }
        ]
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-18
      • 2019-11-28
      相关资源
      最近更新 更多