ASP.NETCore3.1配置HTTPS

目前基于安全考虑,站点采用全站HTTPS成了必然选择,各大浏览器也都一致将HTTP网站标注为不安全或者红色警告。如果配置HTTPS成了迫在眉睫的问题,基于Nginx、Apache、Tomcat等Web服务器对HTTPS支持都很友好,配置比较简单,但是对于使用C#和ASP.NET Core做Web开发的同学可能还有一定的困惑,本文我们就来说说在ASP.NET Core环境下的HTTPS配置。

HTTPS重定向中间件

在asp.net中,默认情况下启用https。其中HttpsRedirection中间件类提供强制执行从http到https重定向。启动时会使用UseHttpsRedirection扩展方法来强制执行此操作。默认情况下,该扩展方法发出307临时重定向响应。然后,使用配置的https端口指定重定向端点。如果没有代码中指定https端口,则该类将从HTTPS_PORT环境变量或IServerAddress功能获取https端口。如果这些变量均未指出,则中间件将发出warning日志,停止重定向。

下面的示例代码展示了,使用中间件将https重定向中间件添加到服务集合的用例。

public void ConfigureServices(IServiceCollection services) { if (!_env.IsDevelopment()) { services.AddHttpsRedirection(opts => { opts.RedirectStatusCode = StatusCodes.Status308PermanentRedirect; opts.HttpsPort = 44300; }); } else { services.AddHttpsRedirection(opts => { opts.RedirectStatusCode = StatusCodes.Status307TemporaryRedirect; opts.HttpsPort = 44300; } services.AddControllers(); } public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseHsts(); } app.UseHttpsRedirection(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); }

代码首先检查环境,并在生产环境中设置对HTTPS的永久的重定向,在开发环境中设置临时性重定向。

生成证书

为了在开发环境中使用HTTPS,必须要生成加密证书。.net core提供了一个全局工具dotnet-dev-certs,使用该工具可在本地环境中创建自签名的证书。可以通过下面命令行安装该工具:

dotnet tool install -global dotnet-dev-certs

安装成功后,就可以用他自签名的证书。

-ep标志表示将生成证书导出的存储目录;

-p标志表示生成证书的密码。

可以使用-trust选项来信任生成的证书。

dotnet dev-certs https -ep <path_to_certficate>/certificate.pfx -p <certificate_password> dotnet dev-certs https -trust

在Linux/Mac OS上,我们可以使用OpenSSL或者OpenGPG来签发证书。下面命令行使用openssl生成2048位,有效期为一年的RSA证书对。第二条命令是使用私钥签发一个人pkcs12格式的公钥用来添加证书信任。

详细参数很多人可能都熟悉,在此不再赘述。

openssl req -new -x509 -newkey rsa:2048 -keyout dev-certificate.key -out dev-certificate.cer -days 365 -subj /CN=localhost

openssl pkcs12 -export -out dev-certificate.pfx -inkey dev-certificate.key -in dev-certificate.cer

使用环境变量ASPNETCORE_Kestrel__Certificates__Default__Path指定证书路径,使用环境变量ASPNETCORE_Kestrel__Certificates__Default__Password制定证书密码

Kestrel作为边缘服务器

Kestrel可以部署为边缘服务器直接对外提供服务,也可以对其添加反向代理对外,支持使用NGINIX, Apache和IIS为代理服务器。

当Kestrel部署为边缘服务器直接对外时候,可以使用以下代码为其配置https:

webBuilder.ConfigureKestrel(serverOptions => { serverOptions.ConfigureHttpsDefaults(listenOptions => { // certificate is an X509Certificate2 listenOptions.ServerCertificate = certificate; }); });

代理模式:

如果使用反向代理(例如Apache或NGNIX)层,则应在调用Https重定向中间件之前配置和设置https转发中间件头。转发的中间件应设置X-Forwarded-Proto头为https。这将启用代理服务器上的https加载和对Web应用程序的纯http调用,并保证原始调用是通过安全的https通道进行的。这在非IIS方案(例如NGINIX或Apache)中尤其重要。

下面的代码用来配置转发的标头中间件:

public void ConfigureServices(IServiceCollection services) { services.AddMvc(); services.Configure<ForwardedHeadersOptions>(options => { options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto; options.KnownNetworks.Clear(); options.KnownProxies.Clear(); }); } public void Configure(IApplicationBuilder app, IHostingEnvironment env) { app.UseForwardedHeaders(); if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Home/Error"); } app.UseMvc(); }

容器化环境中的HTTPS

在容器化环境中,一个选项是在容器创建或启动过程中生成证书,并在docker compose文件中指定证书。然后使用环境文件来配置必要的环境变量,如下所示:

version: "3.7" services: policy_api: container_name: policyadmin_api build: context: . dockerfile: containers/api/Dockerfile volumes: - ./<path_to_certificate>/:/root/.dotnet/https env_file: - containers/api/policyadmin.env networks: - my_network ports: - 5000:5000 - 5001:5001

下面是用于指定必要的环境变量的相应环境文件:

ASPNETCORE_ENVIRONMENT=PreProd ASPNETCORE_URLS=:5001 ASPNETCORE_Kestrel__Certificates__Default__Password=<certificate_password> ASPNETCORE_Kestrel__Certificates__Default__Path=/root/.dotnet/https/certificate.pfx

HTTP严格传输安全

使用HTTPS重定向仍然存在一下较小的安全风险,因为用户可以在重定向到安全HTTPS连接之前使用HTTP发出初始请求。为了解决这个问题,HTTP严格传输安全性(HSTS)协议在响应中添加了一个标头,指示在向Web端点发送请求时仅应使用HTTPS。一旦接收到HSTS标头,即使用户指定了HTTP URL,支持HSTS协议的客户端也将始终使用HTTPS向应用程序发送请求。

在.Net Core 3.1中,可以如下所示将HSTS中间件添加到管道中。

public void ConfigureServices(IServiceCollection services) { // ... services.AddHsts(options => { options.Preload = true; options.IncludeSubDomains = true; options.MaxAge = TimeSpan.FromDays(365); }); //.... }

在上面的代码中,我们指定将HSTS预加载设置为true。HSTS预加载是浏览器内置的功能,通过该列表,主机的全局列表仅在其站点上强制使用HTTPS。域名被硬编码到浏览器中,从而避免了最初的不安全请求,保证仅使用HTTPS。

但是这也会存在一个问题,即使为本地主机指定使用HSTS中间件,使用IPV6和IPV4指定本地地址localhost和回环地址127.0.0.1也不会设置HSTS标头。因为默认情况下,ExcludeHosts参数会排除了这些地址。

总结

总之,.NET CORE提供了两种方法,支持将Kestrel作为边缘服务器或通过SSL/T LS代理来为ASP.net Web应用程序配置https。也支持以docker容器方式配置。