在阅读第4章“使用Kestrel配置和定制HTTPS”时,您可能会产生一些疑问:

  1. 如何使用用户加密机制将密码传递到HTTPS配置?
  2. 您甚至可能想知道是否可以从Program.cs中获取配置?

在本章,我们将通过WebHostBuilderContext这个知识点来解答上面的疑问。

1

还记得在第四章当中,我们在Program.cs这个文件进行WebHostBuilder Kestrel的相关配置。当时我们使用用户秘钥(user secrets)来配置证书密码,如以下代码段所示:

public class Program {     
public static void Main(string[] args)  
{         
    CreateHostBuilder(args).Build().Run();     
}     
public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args).ConfigureWebHostDefaults(webBuilder =>  
{
    webBuilder.UseKestrel(options =>  {
        options.Listen(IPAddress.Loopback, 5000);                         
        options.Listen(IPAddress.Loopback, 5001,listenOptions  => { listenOptions.UseHttps("certificate.pfx","topsecret");  }); }).UseStartup();});
    }
}

此代码段对于.NET 5.0和早期版本仍然有效,对于.NET 6.0中的几乎所有Web项目也有效。但对于使用Web项目模板创建的项目无效,比如你可能通过以下命令行的方式创建项目:

dotnet new web -n HostBuilderConfig -o HostBuilderConfig

.NET 6.0以后的迷你API的Program.cs文件代码如下所示:

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run();

配置在迷你API中看起来是这样的:

using System.Net;
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.UseKestrel(options => {
    options.Listen(IPAddress.Loopback, 5000);     
    options.Listen(IPAddress.Loopback, 5001, listenOptions => {
        listenOptions.UseHttps("certificate.pfx","topsecret");
    });
});

下面的代码适用于.NET 6.0及以前版本中的所有项目模板。

.UseKestrel((host, options) => {     // ... })

第一个参数host是WebHostBuilderContext实例,可以使用它访问配置信息。

builder.WebHost.UseKestrel((host, options) => {     
    var filename = host.Configuration.GetValue("AppSettings:certfilename", "");     
    var password = host.Configuration.GetValue("AppSettings:certpassword", "");     
        options.Listen(IPAddress.Loopback, 5000);     
        options.Listen(IPAddress.Loopback, 5001, listenOptions => {
            listenOptions.UseHttps(filename, password);         
        });
});

在本例中,我们使用冒号分隔符读取Json配置文件里的值,Json文件如下所示:

{     
    "AppSettings": {"certfilename": "certificate.pfx", "certpassword": "topsecret" },     
    "Logging": { "LogLevel": { "Default": "Warning"}},
    "AllowedHosts": "\*"
}
dotnet user-secrets init
dotnet user-secrets set "AppSettings:certfilename" "certificate.pfx"
dotnet user-secrets set "AppSettings:certpassword" "topsecret"

以上也适用于环境变量:

SET APPSETTINGS_CERTFILENAME=certificate.pfx
SET APPSETTINGS_CERTPASSWORD=topsecret

2

以上过程应该如何操作呢?
不知道大家还记不记得 ASP.NET Core 1.0在Startup.cs里的配置方法?当时主要是在StartUp类的构造函数中配置的,添加用户凭证的过程类似,大家可以比对一下:

var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json")
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional:  true);
if (env.IsDevelopment()) {
    builder.AddUserSecrets();
}
builder.AddEnvironmentVariables();
Configuration = builder.Build();

这段代码现在封装在CreateDefaultBuilder方法中,如下所示:

builder.ConfigureAppConfiguration((hostingContext, config) => {
var env = hostingContext.HostingEnvironment;
config.AddJsonFile("appsettings.json",optional: true,reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json",optional: true,reloadOnChange: true);     
    if (env.IsDevelopment()) {       
        var appAssembly = Assembly.Load(new AssemblyName(env.ApplicationName));        
        if (appAssembly != null) {  
            config.AddUserSecrets(appAssembly, optional: true);  
        }
    }     
    config.AddEnvironmentVariables();     
    if (args != null) { config.AddCommandLine(args); }
});

我们看到代码几乎没什么变化,Kestrel支持appsettings.json的文件配置或者使用环境变量指定端口、URL等。我们看下WebHost.cs里的代码:

builder.UseKestrel((builderContext, options) => {
    options.Configure(builderContext.Configuration.GetSection("Kestrel"));
})

以上代码通过appsettings.json文件进行Kestrel相关配置:

"Kestrel": { "EndPoints": {"Http": { "Url": "http://localhost:5555" }} }

或者,可以使用以下环境变量来配置:

SET KESTREL_ENDPOINTS_HTTP_URL=http://localhost:5555

3

好,主体内容介绍差不多了,简单回顾一下本章中介绍的内容:
在Program.cs文件的配置方法中,我们可以通过lambda进行应用程序配置,这里有一个重要的对象WebHostBuilderContext,该对象基本上可以满足我们常用的各自配置需求。
在下一章中,我们将介绍托管模型的详细信息,包括不同的托管模型以及如何通过不同方式托管ASP.NET Core应用程序。

07-26 09:12