强制实施 HTTPS 在 ASP.NET CoreEnforce HTTPS in ASP.NET Core

本文内容

作者:Rick Anderson

本文档介绍如何执行以下操作:

  • 所有请求都需要 HTTPS。
  • 将所有 HTTP 请求重定向到 HTTPS。

任何 API 都不能阻止客户端发送第一个请求上的敏感数据。

警告

API 项目API projects

不要接收敏感信息的 Web Api 使用RequireHttpsAttributeRequireHttpsAttribute 使用 HTTP 状态代码将浏览器从 HTTP 重定向到 HTTPS。API 客户端可能不理解或遵循从 HTTP 到 HTTPS 的重定向。此类客户端可以通过 HTTP 发送信息。Web Api 应:

  • 不侦听 HTTP。
  • 关闭状态代码为400(错误请求)的连接,并且不为请求提供服务。

HSTS 和 API 项目HSTS and API projects

默认 API 项目不包括HSTS ,因为 HSTS 通常是仅限浏览器的指令。其他调用方(如电话或桌面应用程序)遵守说明。即使是在浏览器中,通过 HTTP 对 API 进行单个身份验证调用也会对不安全网络产生风险。安全方法是将 API 项目配置为仅侦听并通过 HTTPS 进行响应。

警告

API 项目API projects

不要接收敏感信息的 Web Api 使用RequireHttpsAttributeRequireHttpsAttribute 使用 HTTP 状态代码将浏览器从 HTTP 重定向到 HTTPS。API 客户端可能不理解或遵循从 HTTP 到 HTTPS 的重定向。此类客户端可以通过 HTTP 发送信息。Web Api 应:

  • 不侦听 HTTP。
  • 关闭状态代码为400(错误请求)的连接,并且不为请求提供服务。

需要 HTTPSRequire HTTPS

建议将生产 ASP.NET Core web 应用使用:

  • HTTPS 重定向中间件(UseHttpsRedirection),用于将 HTTP 请求重定向到 HTTPS。
  • HSTS 中间件(UseHsts)用于向客户端发送 HTTP 严格传输安全协议(HSTS)标头。

备注

使用反向代理配置部署的应用允许代理处理连接安全(HTTPS)。如果代理还处理 HTTPS 重定向,则无需使用 HTTPS 重定向中间件。如果代理服务器还处理写入 HSTS 标头(例如, IIS 10.0 (1709)或更高版本中的本机 HSTS 支持),则应用程序不需要 HSTS 中间件。有关详细信息,请参阅在创建项目时选择退出 HTTPS/HSTS

UseHttpsRedirectionUseHttpsRedirection

下面的代码调用 Startup 类中 UseHttpsRedirection

  1. public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
  2. {
  3. if (env.IsDevelopment())
  4. {
  5. app.UseDeveloperExceptionPage();
  6. }
  7. else
  8. {
  9. app.UseExceptionHandler("/Error");
  10. // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
  11. app.UseHsts();
  12. }
  13. app.UseHttpsRedirection();
  14. app.UseStaticFiles();
  15. app.UseRouting();
  16. app.UseAuthorization();
  17. app.UseEndpoints(endpoints =>
  18. {
  19. endpoints.MapRazorPages();
  20. });
  21. }
  1. public void Configure(IApplicationBuilder app, IHostingEnvironment env)
  2. {
  3. if (env.IsDevelopment())
  4. {
  5. app.UseDeveloperExceptionPage();
  6. }
  7. else
  8. {
  9. app.UseExceptionHandler("/Error");
  10. app.UseHsts();
  11. }
  12. app.UseHttpsRedirection();
  13. app.UseStaticFiles();
  14. app.UseCookiePolicy();
  15. app.UseMvc();
  16. }

前面突出显示的代码:

建议使用临时重定向,而不是永久重定向。链接缓存会导致开发环境中的行为不稳定。如果希望在应用处于非开发环境中时发送永久重定向状态代码,请参阅在生产中配置永久重定向部分。建议使用HSTS向仅应将安全资源请求发送到应用的客户端发送信号(仅在生产中)。

端口配置Port configuration

端口必须可用于中间件,以将不安全的请求重定向到 HTTPS。如果没有可用的端口:

  • 不会重定向到 HTTPS。
  • 中间件记录警告 "无法确定用于重定向的 https 端口"。

使用以下任一方法指定 HTTPS 端口:

  • 设置 "https_port主机" 设置

    • 在 "主机配置" 中。

    • 通过设置 ASPNETCORE_HTTPS_PORT 环境变量。

    • 通过在appsettings中添加顶级条目:

  1. {
  2. "https_port": 443,
  3. "Logging": {
  4. "LogLevel": {
  5. "Default": "Information",
  6. "Microsoft": "Warning",
  7. "Microsoft.Hosting.Lifetime": "Information"
  8. }
  9. },
  10. "AllowedHosts": "*"
  11. }
  • 设置 "https_port主机" 设置

    • 在 "主机配置" 中。

    • 通过设置 ASPNETCORE_HTTPS_PORT 环境变量。

    • 通过在appsettings中添加顶级条目:

  1. {
  2. "https_port": 443,
  3. "Logging": {
  4. "LogLevel": {
  5. "Default": "Warning"
  6. }
  7. },
  8. "AllowedHosts": "*"
  9. }
  • 在开发中,在launchsettings.json中设置 HTTPS URL。当使用 IIS Express 时,启用 HTTPS。

  • Kestrel Server 或http.sys服务器的面向公众的边缘部署配置 HTTPS URL 终结点。此应用只使用一个 HTTPS 端口。中间件通过 IServerAddressesFeature发现端口。

备注

在反向代理配置中运行应用时,IServerAddressesFeature 不可用。使用本部分中所述的其他方法之一设置端口。

Edge 部署Edge deployments

当 Kestrel 或 http.sys 用作面向公众的边缘服务器时,必须将 Kestrel 或 http.sys 配置为侦听两者:

  • 重定向客户端的安全端口(通常为 5001 443)。
  • 不安全端口(在生产5000环境中通常为80)。

客户端必须能够访问不安全的端口,以便应用接收不安全的请求,并将客户端重定向到安全端口。

有关详细信息,请参阅Kestrel 终结点配置ASP.NET Core 中的 HTTP.sys Web 服务器实现

部署方案Deployment scenarios

客户端和服务器之间的任何防火墙都必须为流量打开通信端口。

如果在反向代理配置中转发请求,请在调用 HTTPS 重定向中间件前使用转发的标头中间件转发的标头中间件使用 X-Forwarded-Proto 标头更新 Request.Scheme中间件允许重定向 Uri 和其他安全策略正常工作。当未使用转发的标头中间件时,后端应用程序可能无法接收正确的方案并最终出现在重定向循环中。常见的最终用户错误消息是发生了太多的重定向。

部署到 Azure App Service 时,请按照教程:将现有的自定义 SSL 证书绑定到 Azure Web 应用中的指导进行操作。

选项Options

以下突出显示的代码调用AddHttpsRedirection来配置中间件选项:

  1. public void ConfigureServices(IServiceCollection services)
  2. {
  3. services.AddRazorPages();
  4. services.AddHsts(options =>
  5. {
  6. options.Preload = true;
  7. options.IncludeSubDomains = true;
  8. options.MaxAge = TimeSpan.FromDays(60);
  9. options.ExcludedHosts.Add("example.com");
  10. options.ExcludedHosts.Add("www.example.com");
  11. });
  12. services.AddHttpsRedirection(options =>
  13. {
  14. options.RedirectStatusCode = StatusCodes.Status307TemporaryRedirect;
  15. options.HttpsPort = 5001;
  16. });
  17. }
  1. public void ConfigureServices(IServiceCollection services)
  2. {
  3. services.AddMvc();
  4. services.AddHsts(options =>
  5. {
  6. options.Preload = true;
  7. options.IncludeSubDomains = true;
  8. options.MaxAge = TimeSpan.FromDays(60);
  9. options.ExcludedHosts.Add("example.com");
  10. options.ExcludedHosts.Add("www.example.com");
  11. });
  12. services.AddHttpsRedirection(options =>
  13. {
  14. options.RedirectStatusCode = StatusCodes.Status307TemporaryRedirect;
  15. options.HttpsPort = 5001;
  16. });
  17. }

仅在更改 HttpsPortRedirectStatusCode的值时,才需要调用 AddHttpsRedirection

前面突出显示的代码:

在生产环境中配置永久重定向Configure permanent redirects in production

中间件默认为通过所有重定向发送Status307TemporaryRedirect如果希望在应用处于非开发环境中时发送永久重定向状态代码,请在非开发环境的条件检查中包装中间件选项配置。

Startup.cs中配置服务时:

  1. public void ConfigureServices(IServiceCollection services)
  2. {
  3. // IWebHostEnvironment (stored in _env) is injected into the Startup class.
  4. if (!_env.IsDevelopment())
  5. {
  6. services.AddHttpsRedirection(options =>
  7. {
  8. options.RedirectStatusCode = StatusCodes.Status308PermanentRedirect;
  9. options.HttpsPort = 443;
  10. });
  11. }
  12. }

Startup.cs中配置服务时:

  1. public void ConfigureServices(IServiceCollection services)
  2. {
  3. // IHostingEnvironment (stored in _env) is injected into the Startup class.
  4. if (!_env.IsDevelopment())
  5. {
  6. services.AddHttpsRedirection(options =>
  7. {
  8. options.RedirectStatusCode = StatusCodes.Status308PermanentRedirect;
  9. options.HttpsPort = 443;
  10. });
  11. }
  12. }

HTTPS 重定向中间件备用方法HTTPS Redirection Middleware alternative approach

使用 HTTPS 重定向中间件(UseHttpsRedirection)的一种替代方法是使用 URL 重写中间件(AddRedirectToHttps)。AddRedirectToHttps 还可以在执行重定向时设置状态代码和端口。有关详细信息,请参阅URL 重写中间件

重定向到 HTTPS 时,如果不需要其他重定向规则,我们建议使用本主题中介绍的 HTTPS 重定向中间件(UseHttpsRedirection)。

HTTP 严格传输安全协议(HSTS)HTTP Strict Transport Security Protocol (HSTS)

根据OWASPHTTP 严格传输安全(HSTS)是由 web 应用通过使用响应标头指定的选择加入安全增强功能。支持 HSTS 的浏览器收到此标头时:

  • 浏览器存储域的配置,阻止通过 HTTP 发送任何通信。浏览器强制通过 HTTPS 进行的所有通信。
  • 浏览器阻止用户使用不受信任或无效的证书。浏览器将禁用允许用户暂时信任此类证书的提示。

由于 HSTS 是由客户端强制执行的,因此存在一些限制:

  • 客户端必须支持 HSTS。
  • HSTS 需要至少一个成功的 HTTPS 请求才能建立 HSTS 策略。
  • 应用程序必须检查每个 HTTP 请求并重定向或拒绝 HTTP 请求。

ASP.NET Core 2.1 和更高版本通过 UseHsts 扩展方法实现 HSTS。当应用未处于开发模式时,以下代码将调用 UseHsts

  1. public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
  2. {
  3. if (env.IsDevelopment())
  4. {
  5. app.UseDeveloperExceptionPage();
  6. }
  7. else
  8. {
  9. app.UseExceptionHandler("/Error");
  10. // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
  11. app.UseHsts();
  12. }
  13. app.UseHttpsRedirection();
  14. app.UseStaticFiles();
  15. app.UseRouting();
  16. app.UseAuthorization();
  17. app.UseEndpoints(endpoints =>
  18. {
  19. endpoints.MapRazorPages();
  20. });
  21. }
  1. public void Configure(IApplicationBuilder app, IHostingEnvironment env)
  2. {
  3. if (env.IsDevelopment())
  4. {
  5. app.UseDeveloperExceptionPage();
  6. }
  7. else
  8. {
  9. app.UseExceptionHandler("/Error");
  10. app.UseHsts();
  11. }
  12. app.UseHttpsRedirection();
  13. app.UseStaticFiles();
  14. app.UseCookiePolicy();
  15. app.UseMvc();
  16. }

由于 HSTS 设置由浏览器高度缓存,因此不建议在开发中使用。 UseHsts默认情况下,UseHsts 会排除本地环回地址。

对于第一次实现 HTTPS 的生产环境,请使用 TimeSpan 方法之一将初始HstsOptions设置为较小的值。将值从小时设置为不超过一天,以防需要将 HTTPS 基础结构还原到 HTTP。在你确信 HTTPS 配置的可持续性后,请增加 HSTS max-age 值;常用值为一年。

以下代码:

  1. public void ConfigureServices(IServiceCollection services)
  2. {
  3. services.AddRazorPages();
  4. services.AddHsts(options =>
  5. {
  6. options.Preload = true;
  7. options.IncludeSubDomains = true;
  8. options.MaxAge = TimeSpan.FromDays(60);
  9. options.ExcludedHosts.Add("example.com");
  10. options.ExcludedHosts.Add("www.example.com");
  11. });
  12. services.AddHttpsRedirection(options =>
  13. {
  14. options.RedirectStatusCode = StatusCodes.Status307TemporaryRedirect;
  15. options.HttpsPort = 5001;
  16. });
  17. }
  1. public void ConfigureServices(IServiceCollection services)
  2. {
  3. services.AddMvc();
  4. services.AddHsts(options =>
  5. {
  6. options.Preload = true;
  7. options.IncludeSubDomains = true;
  8. options.MaxAge = TimeSpan.FromDays(60);
  9. options.ExcludedHosts.Add("example.com");
  10. options.ExcludedHosts.Add("www.example.com");
  11. });
  12. services.AddHttpsRedirection(options =>
  13. {
  14. options.RedirectStatusCode = StatusCodes.Status307TemporaryRedirect;
  15. options.HttpsPort = 5001;
  16. });
  17. }
  • 设置 Strict-Transport-Security 标头的预载参数。预加载不属于RFC HSTS 规范,但 web 浏览器支持在全新安装时预加载 HSTS 站点。有关详细信息,请参阅 https://hstspreload.org/
  • 启用includeSubDomain,这会将 HSTS 策略应用到托管子域。
  • Strict-Transport-Security 标头的 max-age 参数显式设置为60天。如果未设置,则默认值为30天。有关详细信息,请参阅最大期限指令
  • example.com 添加到要排除的主机列表。

UseHsts 排除以下环回主机:

  • localhost: IPv4 环回地址。
  • 127.0.0.1: IPv4 环回地址。
  • [::1]: IPv6 环回地址。

在项目创建时选择退出 HTTPS/HSTSOpt-out of HTTPS/HSTS on project creation

在某些后端服务方案中,如果在网络面向公众的边缘处理连接安全,则不需要在每个节点上配置连接安全性。从 Visual Studio 中的模板或从dotnet new命令生成的 Web 应用启用HTTPS 重定向HSTS对于不需要这些方案的部署,可以从模板创建应用时选择退出 HTTPS/HSTS。

选择退出 HTTPS/HSTS:

取消选中 "为 HTTPS 配置" 复选框。

"新建 ASP.NET Core Web 应用程序" 对话框,其中显示未选择 "配置为 HTTPS" 复选框。

"新建 ASP.NET Core Web 应用程序" 对话框,其中显示未选择 "配置为 HTTPS" 复选框。

使用 —no-https 选项。例如:

  1. dotnet new webapp --no-https

信任 Windows 和 macOS 上的 ASP.NET Core HTTPS 开发证书Trust the ASP.NET Core HTTPS development certificate on Windows and macOS

.NET Core SDK 包含 HTTPS 开发证书。此证书作为首次运行体验的一部分进行安装。例如,dotnet —info 生成以下输出的变体:

  1. ASP.NET Core

Successfully installed the ASP.NET Core HTTPS Development Certificate.
To trust the certificate run 'dotnet dev-certs https —trust' (Windows and macOS only).
For establishing trust on other platforms refer to the platform specific documentation.
For more information on configuring HTTPS see https://go.microsoft.com/fwlink/?linkid=848054.

安装 .NET Core SDK 会将 ASP.NET Core HTTPS 开发证书安装到本地用户证书存储。已安装证书,但该证书不受信任。若要信任该证书,请执行一次性步骤以运行 dotnet dev-certs 工具:

  1. dotnet dev-certs https --trust

下面的命令提供有关 dev-certs 工具的帮助:

  1. dotnet dev-certs https --help

如何为 Docker 设置开发人员证书How to set up a developer certificate for Docker

请参阅此 GitHub 问题

从适用于 Linux 的 Windows 子系统信任 HTTPS 证书Trust HTTPS certificate from Windows Subsystem for Linux

适用于 Linux 的 Windows 子系统(WSL)生成 HTTPS 自签名证书。若要将 Windows 证书存储配置为信任 WSL 证书,请执行以下操作:

  • 运行以下命令以导出 WSL 生成的证书: dotnet dev-certs https -ep %USERPROFILE%.aspnet\https\aspnetapp.pfx -p <cryptic-password>

  • 在 WSL 窗口中运行以下命令: ASPNETCORE_KestrelCertificatesDefaultPassword="<cryptic-password>" ASPNETCORE_KestrelCertificatesDefaultPath=/mnt/c/Users/user-name/.aspnet/https/aspnetapp.pfx dotnet watch run

上述命令将设置环境变量,以便 Linux 使用 Windows 受信任的证书。

排查证书问题Troubleshoot certificate problems

本部分提供了在安装和信任ASP.NET Core HTTPS 开发证书时,但仍会出现浏览器警告,指出该证书不受信任。Kestrel使用 ASP.NET Core HTTPS 开发证书。

所有平台-证书不受信任All platforms - certificate not trusted

运行以下命令:

  1. dotnet dev-certs https --clean
  2. dotnet dev-certs https --trust

关闭所有打开的浏览器实例。在应用程序中打开新的浏览器窗口。证书信任由浏览器进行缓存。

前面的命令解决了大多数浏览器信任问题。如果浏览器仍不信任证书,请遵循以下特定于平台的建议。

Docker-证书不受信任Docker - certificate not trusted

  • 删除C:\Users{USER} \AppData\Roaming\ASP.NET\Https文件夹。
  • 清理解决方案。删除 bin 和 obj 文件夹。
  • 重新启动开发工具。例如,Visual Studio、Visual Studio Code 或 Visual Studio for Mac。

Windows-证书不受信任Windows - certificate not trusted

  • 检查证书存储区中的证书。在 Current User > Personal > CertificatesCurrent User > Trusted root certification authorities > Certificates 都应有一个具有 ASP.NET Core HTTPS development certificate 友好名称的 localhost 证书。
  • 从 "个人" 和 "受信任的根证书颁发机构" 中删除所有找到的证书。请勿删除 IIS Express localhost 证书。
  • 运行以下命令:
  1. dotnet dev-certs https --clean
  2. dotnet dev-certs https --trust

关闭所有打开的浏览器实例。在应用程序中打开新的浏览器窗口。

OS X-证书不受信任OS X - certificate not trusted

  • 打开密钥链访问。
  • 选择系统密钥链。
  • 检查是否存在 localhost 证书。
  • 检查它是否在图标上包含 + 符号,以指示其对所有用户都是受信任的。
  • 从系统密钥链中删除证书。
  • 运行以下命令:
  1. dotnet dev-certs https --clean
  2. dotnet dev-certs https --trust

关闭所有打开的浏览器实例。在应用程序中打开新的浏览器窗口。

若要解决 Visual Studio 的证书问题,请参阅使用 IIS Express (dotnet/AspNetCore #16892)进行 HTTPS 错误

用于 Visual Studio 的 IIS Express SSL 证书IIS Express SSL certificate used with Visual Studio

若要解决 IIS Express 证书的问题,请从 Visual Studio 安装程序中选择 "修复"。有关详细信息,请参阅此 GitHub 问题

其他信息Additional information