在 ASP.NET Core 中强制使用 HTTPS

作者:David GalvanRick Anderson

本文介绍如何处理:

  • 对所有请求都要求使用 HTTPS。
  • 将所有 HTTP 请求重定向到 HTTPS。

任何 API 都不能阻止客户端在第一次请求时发送敏感数据。

警告

API 项目

请勿在接收敏感信息的 Web API 上使用 RequireHttpsAttributeRequireHttpsAttributeRequireHttpsAttribute 使用 HTTP 状态代码将浏览器从 HTTP 重定向到 HTTPS。 API 客户端可能不理解或不遵循从 HTTP 到 HTTPS 的重定向。 此类客户端可以通过 HTTP 发送信息。 Web API 应该执行以下操作之一:

  • 不侦听 HTTP。
  • 关闭状态码为 400(错误请求)的连接并且不处理请求。

若要在 API 中禁用 HTTP 重定向,请设置 ASPNETCORE_URLS 环境变量或使用 --urls 命令行标志。 有关详细信息,请参阅 Andrew Lock 撰写的在 ASP.NET Core 中使用多个环境为 ASP.NET Core 应用设置 URL 的 8 种方法

HSTS 和 API 项目

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

HTTP 重定向到 HTTPS 会导致 CORS 预检请求出现 ERR_INVALID_REDIRECT

在 CORS 预检请求时,使用由 UseHttpsRedirection 重定向到 HTTPS 的 HTTP 请求终结点失败,错误为 ERR_INVALID_REDIRECT

API 项目可以拒绝 HTTP 请求,而不是使用 UseHttpsRedirection 将请求重定向到 HTTPS。

需要 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

UseHttpsRedirection

以下代码调用 Program.cs 文件中的 UseHttpsRedirection

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.MapRazorPages();

app.Run();

上述突出显示的代码:

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

端口配置

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

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

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

  • 设置 HttpsRedirectionOptions.HttpsPort

  • 设置 https_port 主机设置

    • 在主机配置中。

    • 通过设置 ASPNETCORE_HTTPS_PORT 环境变量。

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

      {
        "https_port": 443,
        "Logging": {
          "LogLevel": {
            "Default": "Information",
            "Microsoft.AspNetCore": "Warning"
          }
        },
        "AllowedHosts": "*"
      }
      
  • 使用 ASPNETCORE_URLS 环境变量指示使用安全方案的端口。 该环境变量配置服务器。 中间件通过 IServerAddressesFeature 间接发现 HTTPS 端口。 此方法在反向代理部署中不起作用。

  • ASP.NET Core Web 模板在 Properties/launchsettings.json 中为 Kestrel 和 IIS Express 设置 HTTPS URL。 launchsettings.json 仅在本地计算机上使用。

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

注意

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

Edge 部署

KestrelHTTP.sys 用作面向公众的边缘服务器时,必须将 Kestrel 或 HTTP.sys 配置为对这两者进行侦听:

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

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

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

部署方案

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

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

部署到 Azure 应用服务时,请遵循教程:将现有自定义 SSL 证书绑定到 Azure Web 应用中的指导。

选项

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

using static Microsoft.AspNetCore.Http.StatusCodes;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

builder.Services.AddHsts(options =>
{
    options.Preload = true;
    options.IncludeSubDomains = true;
    options.MaxAge = TimeSpan.FromDays(60);
    options.ExcludedHosts.Add("example.com");
    options.ExcludedHosts.Add("www.example.com");
});

builder.Services.AddHttpsRedirection(options =>
{
    options.RedirectStatusCode = Status307TemporaryRedirect;
    options.HttpsPort = 5001;
});

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.MapRazorPages();

app.Run();

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

上述突出显示的代码:

在生产环境中配置永久性重定向

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

Program.cs 中配置服务时:

using static Microsoft.AspNetCore.Http.StatusCodes;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

if (!builder.Environment.IsDevelopment())
{
    builder.Services.AddHttpsRedirection(options =>
    {
        options.RedirectStatusCode = Status308PermanentRedirect;
        options.HttpsPort = 443;
    });
}

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");

    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.MapRazorPages();

app.Run();

HTTPS 重定向中间件替代方法

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

当重定向到 HTTPS 并且不需要其他重定向规则时,建议使用本文所述的 HTTPS 重定向中间件 (UseHttpsRedirection)。

HTTP 严格传输安全协议 (HSTS)

根据 OWASPHTTP 严格传输安全 (HSTS) 是一种可选的安全增强功能,由 Web 应用通过使用响应标头来指定。 当支持 HSTS 的浏览器收到此标头时:

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

由于客户端强制使用 HSTS,因此它存在一些限制:

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

ASP.NET Core 使用 UseHsts 扩展方法实现 HSTS。 当应用未处于开发模式时,以下代码会调用 UseHsts

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.MapRazorPages();

app.Run();

不建议在开发环境中使用 UseHsts,因为 HSTS 设置对浏览器而言是高度可缓存的。 默认情况下,UseHsts 不包括本地环回地址。

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

以下突出显示的代码:

using static Microsoft.AspNetCore.Http.StatusCodes;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

builder.Services.AddHsts(options =>
{
    options.Preload = true;
    options.IncludeSubDomains = true;
    options.MaxAge = TimeSpan.FromDays(60);
    options.ExcludedHosts.Add("example.com");
    options.ExcludedHosts.Add("www.example.com");
});

builder.Services.AddHttpsRedirection(options =>
{
    options.RedirectStatusCode = Status307TemporaryRedirect;
    options.HttpsPort = 5001;
});

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.MapRazorPages();

app.Run();
  • 设置 Strict-Transport-Security 标头的预加载参数。 RFC HSTS 规范中不包含预加载,但 Web 浏览器支持在新安装时预加载 HSTS 站点。 有关详细信息,请参阅 https://hstspreload.org/
  • 启用 includeSubDomain,它会将 HSTS 策略应用于主机子域。
  • Strict-Transport-Security 标头的 max-age 参数显式设置为 60 天。 如果未设置,则默认为 30 天。 有关详细信息,请参阅 max-age 指令
  • example.com 添加到要排除的主机列表中。

UseHsts 不包括以下环回主机:

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

在项目创建时选择退出 HTTPS/HSTS

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

若要选择退出 HTTPS/HSTS,请执行以下操作:

取消选中“针对 HTTPS 进行配置”复选框。

未选中“配置 HTTPS”复选框的“新建 ASP.NET Core Web 应用程序”对话框。

信任 ASP.NET Core HTTPS 开发证书

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

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 工具:

dotnet dev-certs https --trust

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

dotnet dev-certs https --help

警告

请勿在将被重新分发的环境中创建开发证书,例如容器映像或虚拟机。 这样做可能会导致欺骗和特权提升。 为了帮助防止出现这种情况,请在第一次调用 .NET CLI 之前,将 DOTNET_GENERATE_ASPNET_CERTIFICATE 环境变量设置为 false。 这将在 CLI 的首次运行体验期间跳过自动生成 ASP.NET Core 开发证书。

如何为 Docker 设置开发人员证书

请参阅此 GitHub 问题

特定于 Linux 的注意事项

Linux 发行版在将证书标记为受信任的方式上存在很大差异。 虽然 dotnet dev-certs 预计广泛适用,但它仅在 Ubuntu 和 Fedora 上得到正式支持,专门旨在确保对基于 Firefox 和 Chromium 的浏览器(Edge、Chrome 和 Chromium)的信任。

依赖项

若要建立 OpenSSL 信任,该 openssl 工具必须位于路径上。

若要建立浏览器信任(例如在 Edge 或 Firefox 中),该 certutil 工具必须位于路径上。

OpenSSL 信任

当 ASP.NET Core 开发证书受信任时,该证书将导出到当前用户的 home 目录的文件夹中。 若要让 OpenSSL(和使用它的客户端)选取此文件夹,需要设置 SSL_CERT_DIR 环境变量。 可以在单个会话中执行此操作,方法是运行类似于 export SSL_CERT_DIR=$HOME/.aspnet/dev-certs/trust:/usr/lib/ssl/certs 的命令(传递 --verbose 时,确切值会出现在输出中)或将其添加到(特定于发行版和 shell 的)配置文件(例如 .profile)。

这是使 curl 等工具信任开发证书所必需的。 或者,也可以将 -CAfile-CApath 传递给每个单独的 curl 调用。

请注意,这需要 1.1.1h 或更高版本或 3.0.0 或更高版本,具体取决于所使用的主版本。

如果 OpenSSL 信任陷入错误状态(例如,dotnet dev-certs https --clean 无法删除它),通常可以使用 c_rehash 工具将其恢复正常。

覆盖

如果使用具有自己的网络安全服务 (NSS) 存储区的其他浏览器,则可以使用 DOTNET_DEV_CERTS_NSSDB_PATHS 环境变量来指定一个以冒号分隔的 NSS 目录(例如,包含 cert9.db 的目录)列表,以便向其添加开发证书。

如果将希望 OpenSSL 信任的证书存储在特定目录中,则可以使用 DOTNET_DEV_CERTS_OPENSSL_CERTIFICATE_DIRECTORY 环境变量来指示其位置。

警告

如果设置其中任一变量,请务必在每次更新信任时将其设置为相同的值。 如果它们更改,工具就无法知道在以前位置上的证书(例如清理证书)。

使用 sudo

与其他平台上一样,开发证书是针对每个用户单独存储和信任的。 因此,如果以不同的用户身份运行 dotnet dev-certs(例如通过使用 sudo),信任开发证书的将是那个用户(例如 root)。

在 Linux 上使用 linux-dev-certs 信任 HTTPS 证书

linux-dev-certs 是一种开源、社区支持的 .NET 全局工具,可快捷地在 Linux 上创建和信任开发人员证书。 该工具不由 Microsoft 进行支持或维护。

以下命令安装该工具并创建受信任的开发人员证书:

dotnet tool update -g linux-dev-certs
dotnet linux-dev-certs install

有关详细信息或要报告问题,请参阅 linux-dev-certs GitHub 存储库

排查证书问题,例如证书不受信任

如果 ASP.NET Core HTTPS 开发证书已安装且受信任,但仍收到证书不受信任的浏览器警告,则本部分可提供帮助。 ASP.NET Core HTTPS 开发证书由 Kestrel 使用。

若要修复 IIS Express 证书,请参阅此 Stackoverflow 问题。

所有平台 - 证书不受信任

运行以下命令:

dotnet dev-certs https --clean
dotnet dev-certs https --trust

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

dotnet dev-certs https --clean 失败

上述命令可解决大多数浏览器信任问题。 如果浏览器仍不信任证书,请按照以下特定于该平台的建议操作。

Docker - 证书不受信任

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

Windows - 证书不受信任

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

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

OS X - 证书不受信任

  • 打开“密钥链访问”。
  • 选择“系统密钥链”。
  • 检查是否存在 localhost 证书。
  • 检查其图标上是否包含 + 符号,以表明它对于所有用户而言均受信任。
  • 从系统密钥链中删除证书。
  • 运行以下命令:
dotnet dev-certs https --clean
dotnet dev-certs https --trust

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

若要排查 Visual Studio 的证书问题,请参阅使用 IIS Express 时出现 HTTPS 错误 (dotnet/AspNetCore #16892)

Linux 证书不受信任

检查配置为信任的证书是否为 Kestrel 服务器将使用的用户 HTTPS 开发人员证书。

在以下位置检查当前用户默认的 HTTPS 开发人员 Kestrel 证书:

ls -la ~/.dotnet/corefx/cryptography/x509stores/my

HTTPS 开发人员 Kestrel 证书文件是 SHA1 指纹。 当通过 dotnet dev-certs https --clean 删除该文件时,会根据需要使用不同的指纹重新生成。 使用以下命令检查导出证书的指纹是否匹配:

openssl x509 -noout -fingerprint -sha1 -inform pem -in /usr/local/share/ca-certificates/aspnet/https.crt

如果该证书不匹配,则可能是以下情况之一:

  • 旧证书。
  • 为根用户导出了开发人员证书。 对于这种情况,请导出证书。

可在以下位置检查根用户证书:

ls -la /root/.dotnet/corefx/cryptography/x509stores/my

将 IIS Express SSL 证书与 Visual Studio 一起使用

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

组策略可阻止信任自签名证书

在某些情况下,组策略可能会阻止信任自签名证书。 有关详细信息,请参阅此 GitHub 问题

其他信息

注意

如果你使用的是 .NET 9 SDK 或更高版本,请参阅本文的 .NET 9 版本中更新的 Linux 操作流程。

警告

API 项目

请勿在接收敏感信息的 Web API 上使用 RequireHttpsAttributeRequireHttpsAttributeRequireHttpsAttribute 使用 HTTP 状态代码将浏览器从 HTTP 重定向到 HTTPS。 API 客户端可能不理解或不遵循从 HTTP 到 HTTPS 的重定向。 此类客户端可以通过 HTTP 发送信息。 Web API 应该执行以下操作之一:

  • 不侦听 HTTP。
  • 关闭状态码为 400(错误请求)的连接并且不处理请求。

若要在 API 中禁用 HTTP 重定向,请设置 ASPNETCORE_URLS 环境变量或使用 --urls 命令行标志。 有关详细信息,请参阅 Andrew Lock 撰写的在 ASP.NET Core 中使用多个环境为 ASP.NET Core 应用设置 URL 的 8 种方法

HSTS 和 API 项目

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

HTTP 重定向到 HTTPS 会导致 CORS 预检请求出现 ERR_INVALID_REDIRECT

在 CORS 预检请求时,使用由 UseHttpsRedirection 重定向到 HTTPS 的 HTTP 请求终结点失败,错误为 ERR_INVALID_REDIRECT

API 项目可以拒绝 HTTP 请求,而不是使用 UseHttpsRedirection 将请求重定向到 HTTPS。

需要 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

UseHttpsRedirection

以下代码调用 Program.cs 文件中的 UseHttpsRedirection

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.MapRazorPages();

app.Run();

上述突出显示的代码:

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

端口配置

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

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

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

  • 设置 HttpsRedirectionOptions.HttpsPort

  • 设置 https_port 主机设置

    • 在主机配置中。

    • 通过设置 ASPNETCORE_HTTPS_PORT 环境变量。

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

      {
        "https_port": 443,
        "Logging": {
          "LogLevel": {
            "Default": "Information",
            "Microsoft.AspNetCore": "Warning"
          }
        },
        "AllowedHosts": "*"
      }
      
  • 使用 ASPNETCORE_URLS 环境变量指示使用安全方案的端口。 该环境变量配置服务器。 中间件通过 IServerAddressesFeature 间接发现 HTTPS 端口。 此方法在反向代理部署中不起作用。

  • ASP.NET Core Web 模板在 Properties/launchsettings.json 中为 Kestrel 和 IIS Express 设置 HTTPS URL。 launchsettings.json 仅在本地计算机上使用。

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

注意

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

Edge 部署

KestrelHTTP.sys 用作面向公众的边缘服务器时,必须将 Kestrel 或 HTTP.sys 配置为对这两者进行侦听:

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

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

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

部署方案

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

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

部署到 Azure 应用服务时,请遵循教程:将现有自定义 SSL 证书绑定到 Azure Web 应用中的指导。

选项

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

using static Microsoft.AspNetCore.Http.StatusCodes;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

builder.Services.AddHsts(options =>
{
    options.Preload = true;
    options.IncludeSubDomains = true;
    options.MaxAge = TimeSpan.FromDays(60);
    options.ExcludedHosts.Add("example.com");
    options.ExcludedHosts.Add("www.example.com");
});

builder.Services.AddHttpsRedirection(options =>
{
    options.RedirectStatusCode = Status307TemporaryRedirect;
    options.HttpsPort = 5001;
});

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.MapRazorPages();

app.Run();

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

上述突出显示的代码:

在生产环境中配置永久性重定向

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

Program.cs 中配置服务时:

using static Microsoft.AspNetCore.Http.StatusCodes;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

if (!builder.Environment.IsDevelopment())
{
    builder.Services.AddHttpsRedirection(options =>
    {
        options.RedirectStatusCode = Status308PermanentRedirect;
        options.HttpsPort = 443;
    });
}

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");

    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.MapRazorPages();

app.Run();

HTTPS 重定向中间件替代方法

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

当重定向到 HTTPS 并且不需要其他重定向规则时,建议使用本文所述的 HTTPS 重定向中间件 (UseHttpsRedirection)。

HTTP 严格传输安全协议 (HSTS)

根据 OWASPHTTP 严格传输安全 (HSTS) 是一种可选的安全增强功能,由 Web 应用通过使用响应标头来指定。 当支持 HSTS 的浏览器收到此标头时:

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

由于客户端强制使用 HSTS,因此它存在一些限制:

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

ASP.NET Core 使用 UseHsts 扩展方法实现 HSTS。 当应用未处于开发模式时,以下代码会调用 UseHsts

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.MapRazorPages();

app.Run();

不建议在开发环境中使用 UseHsts,因为 HSTS 设置对浏览器而言是高度可缓存的。 默认情况下,UseHsts 不包括本地环回地址。

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

以下突出显示的代码:

using static Microsoft.AspNetCore.Http.StatusCodes;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

builder.Services.AddHsts(options =>
{
    options.Preload = true;
    options.IncludeSubDomains = true;
    options.MaxAge = TimeSpan.FromDays(60);
    options.ExcludedHosts.Add("example.com");
    options.ExcludedHosts.Add("www.example.com");
});

builder.Services.AddHttpsRedirection(options =>
{
    options.RedirectStatusCode = Status307TemporaryRedirect;
    options.HttpsPort = 5001;
});

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.MapRazorPages();

app.Run();
  • 设置 Strict-Transport-Security 标头的预加载参数。 RFC HSTS 规范中不包含预加载,但 Web 浏览器支持在新安装时预加载 HSTS 站点。 有关详细信息,请参阅 https://hstspreload.org/
  • 启用 includeSubDomain,它会将 HSTS 策略应用于主机子域。
  • Strict-Transport-Security 标头的 max-age 参数显式设置为 60 天。 如果未设置,则默认为 30 天。 有关详细信息,请参阅 max-age 指令
  • example.com 添加到要排除的主机列表中。

UseHsts 不包括以下环回主机:

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

在项目创建时选择退出 HTTPS/HSTS

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

若要选择退出 HTTPS/HSTS,请执行以下操作:

取消选中“针对 HTTPS 进行配置”复选框。

未选中“配置 HTTPS”复选框的“新建 ASP.NET Core Web 应用程序”对话框。

信任 Windows 和 macOS 上的 ASP.NET Core HTTPS 开发证书

对于 Firefox 浏览器,请参阅下一部分。

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

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 工具:

dotnet dev-certs https --trust

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

dotnet dev-certs https --help

警告

请勿在将被重新分发的环境中创建开发证书,例如容器映像或虚拟机。 这样做可能会导致欺骗和特权提升。 为了帮助防止出现这种情况,请在第一次调用 .NET CLI 之前,将 DOTNET_GENERATE_ASPNET_CERTIFICATE 环境变量设置为 false。 这将在 CLI 的首次运行体验期间跳过自动生成 ASP.NET Core 开发证书。

使用 Firefox 信任 HTTPS 证书以防止出现 SEC_ERROR_INADEQUATE_KEY_USAGE 错误

Firefox 浏览器使用自己的证书存储,因此不信任 IIS ExpressKestrel 开发人员证书。

使用 Firefox 信任 HTTPS 证书有两种方法:创建策略文件或使用 FireFox 浏览器进行配置。 配置该浏览器会创建策略文件,因此这两种方法是等效的。

创建策略文件以使用 Firefox 信任 HTTPS 证书

在以下位置复制策略文件 (policies.json):

将以下 JSON 添加到 Firefox 策略文件:

{
  "policies": {
    "Certificates": {
      "ImportEnterpriseRoots": true
    }
  }
}

前面的策略文件使 Firefox 信任证书,这些证书来自 Windows 证书存储中的受信任证书。 下一部分提供了另一种方法来使用 Firefox 浏览器创建上述策略文件。

使用 Firefox 浏览器配置 HTTPS 证书信任

使用以下说明设置 security.enterprise_roots.enabled = true

  1. 在 FireFox 浏览器中输入 about:config
  2. 如果你接受风险,请选择“接受风险并继续”。
  3. 选择“全部显示”
  4. 设置 security.enterprise_roots.enabled = true
  5. 退出并重启 Firefox

有关详细信息,请参阅在 Firefox 中设置证书颁发机构 (CA)mozilla/policy-templates/README 文件

如何为 Docker 设置开发人员证书

请参阅此 GitHub 问题

在 Linux 上信任 HTTPS 证书

建立信任是特定于发行版和浏览器的。 以下部分提供了针对一些常用发行版和 Chromium 浏览器(Edge 和 Chrome)以及针对 Firefox 的说明。

在 Linux 上使用 linux-dev-certs 信任 HTTPS 证书

linux-dev-certs 是一种开源、社区支持的 .NET 全局工具,可快捷地在 Linux 上创建和信任开发人员证书。 该工具不由 Microsoft 进行支持或维护。

以下命令安装该工具并创建受信任的开发人员证书:

dotnet tool update -g linux-dev-certs
dotnet linux-dev-certs install

有关详细信息或要报告问题,请参阅 linux-dev-certs GitHub 存储库

Ubuntu 信任用于进行服务到服务通信的证书

以下说明不适用于某些 Ubuntu 版本,例如 20.04。 有关详细信息,请参阅 GitHub 问题 dotnet/AspNetCore.Docs #23686

  1. 安装 OpenSSL 1.1.1h 或更高版本。 有关如何更新 OpenSSL 的说明,请参阅你的发行版。

  2. 运行以下命令:

    dotnet dev-certs https
    sudo -E dotnet dev-certs https -ep /usr/local/share/ca-certificates/aspnet/https.crt --format PEM
    sudo update-ca-certificates
    

前面的命令:

  • 确保创建了当前用户的开发人员证书。
  • 使用当前用户的环境导出具有 ca-certificates 文件夹所需的提升权限的证书。
  • 删除 -E 标志会导出根用户证书,并根据需要生成它。 每个新生成的证书都有不同的指纹。 以根用户身份运行时,不需要 sudo-E

上述命令中的路径特定于 Ubuntu。 对于其他发行版,请选择相应的路径或使用证书颁发机构 (CA) 的路径。

在 Linux 上使用 Edge 或 Chrome 信任 HTTPS 证书

对于 Linux 上的 chromium 浏览器:

  • 为你的发行版安装 libnss3-tools

  • 创建 $HOME/.pki/nssdb 文件夹或验证计算机上是否存在该文件夹。

  • 使用以下命令导出证书:

    dotnet dev-certs https
    sudo -E dotnet dev-certs https -ep /usr/local/share/ca-certificates/aspnet/https.crt --format PEM
    

    上述命令中的路径特定于 Ubuntu。 对于其他发行版,请选择相应的路径或使用证书颁发机构 (CA) 的路径。

  • 运行以下命令:

    certutil -d sql:$HOME/.pki/nssdb -A -t "P,," -n localhost -i /usr/local/share/ca-certificates/aspnet/https.crt
    
  • 退出并重启浏览器。

在 Linux 上使用 Firefox 信任证书

  • 使用以下命令导出证书:

    dotnet dev-certs https
    sudo -E dotnet dev-certs https -ep /usr/local/share/ca-certificates/aspnet/https.crt --format PEM
    

    上述命令中的路径特定于 Ubuntu。 对于其他发行版,请选择相应的路径或使用证书颁发机构 (CA) 的路径。

  • 使用以下命令在 /usr/lib/firefox/distribution/policies.json 创建 JSON 文件:

cat <<EOF | sudo tee /usr/lib/firefox/distribution/policies.json
{
    "policies": {
        "Certificates": {
            "Install": [
                "/usr/local/share/ca-certificates/aspnet/https.crt"
            ]
        }
    }
}
EOF

注意:Ubuntu 21.10 Firefox 作为快照包提供,安装文件夹为 /snap/firefox/current/usr/lib/firefox

有关使用浏览器配置策略文件的替代方法,请参阅本文中的使用 Firefox 浏览器配置 HTTPS 证书信任

使用 Fedora 34 信任证书

请参阅:

使用其他发行版信任证书

请参阅此 GitHub 问题

信任来自适用于 Linux 的 Windows 子系统的 HTTPS 证书

以下说明不适用于某些 Linux 发行版,例如 Ubuntu 20.04。 有关详细信息,请参阅 GitHub 问题 dotnet/AspNetCore.Docs #23686

适用于 Linux 的 Windows 子系统 (WSL) 生成 HTTPS 自签名开发证书,默认情况下,该证书在 Windows 中不受信任。 让 Windows 信任 WSL 证书的最简单方法是将 WSL 配置为使用与 Windows 相同的证书:

  • Windows 上,将开发者证书导出到文件:

    dotnet dev-certs https -ep https.pfx -p $CREDENTIAL_PLACEHOLDER$ --trust
    

    其中 $CREDENTIAL_PLACEHOLDER$ 是密码。

  • 在 WSL 窗口中,将导出的证书导入 WSL 实例:

    dotnet dev-certs https --clean --import <<path-to-pfx>> --password $CREDENTIAL_PLACEHOLDER$
    

上述方法是按每个证书和每个 WSL 发行版进行的一次性操作。 这比反复导出证书更容易。 如果在 Windows 上更新或重新生成证书,则可能需要再次运行上述命令。

排查证书问题,例如证书不受信任

如果 ASP.NET Core HTTPS 开发证书已安装且受信任,但仍收到证书不受信任的浏览器警告,则本部分可提供帮助。 ASP.NET Core HTTPS 开发证书由 Kestrel 使用。

若要修复 IIS Express 证书,请参阅此 Stackoverflow 问题。

所有平台 - 证书不受信任

运行以下命令:

dotnet dev-certs https --clean
dotnet dev-certs https --trust

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

dotnet dev-certs https --clean 失败

上述命令可解决大多数浏览器信任问题。 如果浏览器仍不信任证书,请按照以下特定于该平台的建议操作。

Docker - 证书不受信任

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

Windows - 证书不受信任

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

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

OS X - 证书不受信任

  • 打开“密钥链访问”。
  • 选择“系统密钥链”。
  • 检查是否存在 localhost 证书。
  • 检查其图标上是否包含 + 符号,以表明它对于所有用户而言均受信任。
  • 从系统密钥链中删除证书。
  • 运行以下命令:
dotnet dev-certs https --clean
dotnet dev-certs https --trust

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

若要排查 Visual Studio 的证书问题,请参阅使用 IIS Express 时出现 HTTPS 错误 (dotnet/AspNetCore #16892)

Linux 证书不受信任

检查配置为信任的证书是否为 Kestrel 服务器将使用的用户 HTTPS 开发人员证书。

在以下位置检查当前用户默认的 HTTPS 开发人员 Kestrel 证书:

ls -la ~/.dotnet/corefx/cryptography/x509stores/my

HTTPS 开发人员 Kestrel 证书文件是 SHA1 指纹。 当通过 dotnet dev-certs https --clean 删除该文件时,会根据需要使用不同的指纹重新生成。 使用以下命令检查导出证书的指纹是否匹配:

openssl x509 -noout -fingerprint -sha1 -inform pem -in /usr/local/share/ca-certificates/aspnet/https.crt

如果该证书不匹配,则可能是以下情况之一:

  • 旧证书。
  • 为根用户导出了开发人员证书。 对于这种情况,请导出证书。

可在以下位置检查根用户证书:

ls -la /root/.dotnet/corefx/cryptography/x509stores/my

将 IIS Express SSL 证书与 Visual Studio 一起使用

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

组策略可阻止信任自签名证书

在某些情况下,组策略可能会阻止信任自签名证书。 有关详细信息,请参阅此 GitHub 问题

其他信息

警告

API 项目

请勿在接收敏感信息的 Web API 上使用 RequireHttpsAttributeRequireHttpsAttributeRequireHttpsAttribute 使用 HTTP 状态代码将浏览器从 HTTP 重定向到 HTTPS。 API 客户端可能不理解或不遵循从 HTTP 到 HTTPS 的重定向。 此类客户端可以通过 HTTP 发送信息。 Web API 应该执行以下操作之一:

  • 不侦听 HTTP。
  • 关闭状态码为 400(错误请求)的连接并且不处理请求。

若要在 API 中禁用 HTTP 重定向,请设置 ASPNETCORE_URLS 环境变量或使用 --urls 命令行标志。 有关详细信息,请参阅 Andrew Lock 撰写的在 ASP.NET Core 中使用多个环境为 ASP.NET Core 应用设置 URL 的 5 种方法

HSTS 和 API 项目

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

需要 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

UseHttpsRedirection

以下代码调用 Startup 类中的 UseHttpsRedirection

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Error");
        // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
        app.UseHsts();
    }

    app.UseHttpsRedirection();
    app.UseStaticFiles();

    app.UseRouting();

    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapRazorPages();
    });
}

上述突出显示的代码:

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

端口配置

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

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

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

  • 设置 HttpsRedirectionOptions.HttpsPort

  • 设置 https_port 主机设置

    • 在主机配置中。

    • 通过设置 ASPNETCORE_HTTPS_PORT 环境变量。

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

      {
          "https_port": 443,
          "Logging": {
              "LogLevel": {
                  "Default": "Information",
                  "Microsoft": "Warning",
                  "Microsoft.Hosting.Lifetime": "Information"
              }
          },
          "AllowedHosts": "*"
      }
      
  • 使用 ASPNETCORE_URLS 环境变量指示使用安全方案的端口。 该环境变量配置服务器。 中间件通过 IServerAddressesFeature 间接发现 HTTPS 端口。 此方法在反向代理部署中不起作用。

  • 在开发环境中,在 launchsettings.json 中设置 HTTPS URL。 使用 IIS Express 时启用 HTTPS。

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

注意

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

Edge 部署

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

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

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

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

部署方案

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

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

部署到 Azure 应用服务时,请遵循教程:将现有自定义 SSL 证书绑定到 Azure Web 应用中的指导。

选项

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

public void ConfigureServices(IServiceCollection services)
{
    services.AddRazorPages();

    services.AddHsts(options =>
    {
        options.Preload = true;
        options.IncludeSubDomains = true;
        options.MaxAge = TimeSpan.FromDays(60);
        options.ExcludedHosts.Add("example.com");
        options.ExcludedHosts.Add("www.example.com");
    });

    services.AddHttpsRedirection(options =>
    {
        options.RedirectStatusCode = (int) HttpStatusCode.TemporaryRedirect;
        options.HttpsPort = 5001;
    });
}

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

上述突出显示的代码:

在生产环境中配置永久性重定向

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

Startup.cs 中配置服务时:

public void ConfigureServices(IServiceCollection services)
{
    // IWebHostEnvironment (stored in _env) is injected into the Startup class.
    if (!_env.IsDevelopment())
    {
        services.AddHttpsRedirection(options =>
        {
            options.RedirectStatusCode = (int) HttpStatusCode.PermanentRedirect;
            options.HttpsPort = 443;
        });
    }
}

HTTPS 重定向中间件替代方法

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

当重定向到 HTTPS 并且不需要其他重定向规则时,建议使用本文所述的 HTTPS 重定向中间件 (UseHttpsRedirection)。

HTTP 严格传输安全协议 (HSTS)

根据 OWASPHTTP 严格传输安全 (HSTS) 是一种可选的安全增强功能,由 Web 应用通过使用响应标头来指定。 当支持 HSTS 的浏览器收到此标头时:

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

由于客户端强制使用 HSTS,因此它存在一些限制:

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

ASP.NET Core 使用 UseHsts 扩展方法实现 HSTS。 当应用未处于开发模式时,以下代码会调用 UseHsts

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Error");
        // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
        app.UseHsts();
    }

    app.UseHttpsRedirection();
    app.UseStaticFiles();

    app.UseRouting();

    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapRazorPages();
    });
}

不建议在开发环境中使用 UseHsts,因为 HSTS 设置对浏览器而言是高度可缓存的。 默认情况下,UseHsts 不包括本地环回地址。

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

下面的代码:

public void ConfigureServices(IServiceCollection services)
{
    services.AddRazorPages();

    services.AddHsts(options =>
    {
        options.Preload = true;
        options.IncludeSubDomains = true;
        options.MaxAge = TimeSpan.FromDays(60);
        options.ExcludedHosts.Add("example.com");
        options.ExcludedHosts.Add("www.example.com");
    });

    services.AddHttpsRedirection(options =>
    {
        options.RedirectStatusCode = (int) HttpStatusCode.TemporaryRedirect;
        options.HttpsPort = 5001;
    });
}
  • 设置 Strict-Transport-Security 标头的预加载参数。 RFC HSTS 规范中不包含预加载,但 Web 浏览器支持在新安装时预加载 HSTS 站点。 有关详细信息,请参阅 https://hstspreload.org/
  • 启用 includeSubDomain,它会将 HSTS 策略应用于主机子域。
  • Strict-Transport-Security 标头的 max-age 参数显式设置为 60 天。 如果未设置,则默认为 30 天。 有关详细信息,请参阅 max-age 指令
  • example.com 添加到要排除的主机列表中。

UseHsts 不包括以下环回主机:

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

在项目创建时选择退出 HTTPS/HSTS

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

若要选择退出 HTTPS/HSTS,请执行以下操作:

取消选中“针对 HTTPS 进行配置”复选框。

新的 ASP.NET 核心 Web 应用模板的其他信息对话框,其中显示了“配置 HTTPS”复选框

信任 Windows 和 macOS 上的 ASP.NET Core HTTPS 开发证书

对于 Firefox 浏览器,请参阅下一部分。

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

Installed an ASP.NET Core HTTPS development certificate.
To trust the certificate, run 'dotnet dev-certs https --trust'
Learn about HTTPS: https://aka.ms/dotnet-https

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

dotnet dev-certs https --trust

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

dotnet dev-certs https --help

警告

请勿在将被重新分发的环境中创建开发证书,例如容器映像或虚拟机。 这样做可能会导致欺骗和特权提升。 为了帮助防止出现这种情况,请在第一次调用 .NET CLI 之前,将 DOTNET_GENERATE_ASPNET_CERTIFICATE 环境变量设置为 false。 这将在 CLI 的首次运行体验期间跳过自动生成 ASP.NET Core 开发证书。

使用 Firefox 信任 HTTPS 证书以防止出现 SEC_ERROR_INADEQUATE_KEY_USAGE 错误

Firefox 浏览器使用自己的证书存储,因此不信任 IIS ExpressKestrel 开发人员证书。

使用 Firefox 信任 HTTPS 证书有两种方法:创建策略文件或使用 FireFox 浏览器进行配置。 配置该浏览器会创建策略文件,因此这两种方法是等效的。

创建策略文件以使用 Firefox 信任 HTTPS 证书

在以下位置复制策略文件 (policies.json):

将以下 JSON 添加到 Firefox 策略文件:

{
  "policies": {
    "Certificates": {
      "ImportEnterpriseRoots": true
    }
  }
}

前面的策略文件使 Firefox 信任证书,这些证书来自 Windows 证书存储中的受信任证书。 下一部分提供了另一种方法来使用 Firefox 浏览器创建上述策略文件。

使用 Firefox 浏览器配置 HTTPS 证书信任

使用以下说明设置 security.enterprise_roots.enabled = true

  1. 在 FireFox 浏览器中输入 about:config
  2. 如果你接受风险,请选择“接受风险并继续”。
  3. 选择“全部显示”。
  4. 设置 security.enterprise_roots.enabled = true
  5. 退出并重启 Firefox。

有关详细信息,请参阅在 Firefox 中设置证书颁发机构 (CA)mozilla/policy-templates/README 文件

如何为 Docker 设置开发人员证书

请参阅此 GitHub 问题

在 Linux 上信任 HTTPS 证书

建立信任是特定于发行版和浏览器的。 以下部分提供了针对一些常用发行版和 Chromium 浏览器(Edge 和 Chrome)以及针对 Firefox 的说明。

Ubuntu 信任用于进行服务到服务通信的证书

  1. 安装 OpenSSL 1.1.1h 或更高版本。 有关如何更新 OpenSSL 的说明,请参阅你的发行版。

  2. 运行以下命令:

    dotnet dev-certs https
    sudo -E dotnet dev-certs https -ep /usr/local/share/ca-certificates/aspnet/https.crt --format PEM
    sudo update-ca-certificates
    

前面的命令:

  • 确保创建了当前用户的开发人员证书。
  • 使用当前用户的环境导出具有 ca-certificates 文件夹所需提升权限的证书。
  • 移除 -E 标志会导出根用户证书,并根据需要生成它。 每个新生成的证书都有不同的指纹。 以根用户身份运行时,不需要 sudo-E

上述命令中的路径特定于 Ubuntu。 对于其他发行版,请选择相应的路径或使用证书颁发机构 (CA) 的路径。

在 Linux 上使用 Edge 或 Chrome 信任 HTTPS 证书

对于 Linux 上的 chromium 浏览器:

  • 为你的发行版安装 libnss3-tools

  • 创建 $HOME/.pki/nssdb 文件夹或验证计算机上是否存在该文件夹。

  • 使用以下命令导出证书:

    dotnet dev-certs https
    sudo -E dotnet dev-certs https -ep /usr/local/share/ca-certificates/aspnet/https.crt --format PEM
    

    上述命令中的路径特定于 Ubuntu。 对于其他发行版,请选择相应的路径或使用证书颁发机构 (CA) 的路径。

  • 运行以下命令:

    certutil -d sql:$HOME/.pki/nssdb -A -t "P,," -n localhost -i /usr/local/share/ca-certificates/aspnet/https.crt
    
  • 退出并重启浏览器。

在 Linux 上使用 Firefox 信任证书

  • 使用以下命令导出证书:

    dotnet dev-certs https
    sudo -E dotnet dev-certs https -ep /usr/local/share/ca-certificates/aspnet/https.crt --format PEM
    

    上述命令中的路径特定于 Ubuntu。 对于其他发行版,请选择相应的路径或使用证书颁发机构 (CA) 的路径。

  • /usr/lib/firefox/distribution/policies.json 中创建一个 JSON 文件,其中包含以下内容:

cat <<EOF | sudo tee /usr/lib/firefox/distribution/policies.json
{
    "policies": {
        "Certificates": {
            "Install": [
                "/usr/local/share/ca-certificates/aspnet/https.crt"
            ]
        }
    }
}
EOF

有关使用浏览器配置策略文件的替代方法,请参阅本文中的使用 Firefox 浏览器配置 HTTPS 证书信任

使用 Fedora 34 信任证书

Fedora 上的 Firefox

echo 'pref("general.config.filename", "firefox.cfg");
pref("general.config.obscure_value", 0);' > ./autoconfig.js

echo '//Enable policies.json
lockPref("browser.policies.perUserDir", false);' > firefox.cfg

echo "{
    \"policies\": {
        \"Certificates\": {
            \"Install\": [
                \"aspnetcore-localhost-https.crt\"
            ]
        }
    }
}" > policies.json

dotnet dev-certs https -ep localhost.crt --format PEM

sudo mv autoconfig.js /usr/lib64/firefox/
sudo mv firefox.cfg /usr/lib64/firefox/
sudo mv policies.json /usr/lib64/firefox/distribution/
mkdir -p ~/.mozilla/certificates
cp localhost.crt ~/.mozilla/certificates/aspnetcore-localhost-https.crt
rm localhost.crt

在 Fedora 上信任 dotnet-to-dotnet

sudo cp localhost.crt /etc/pki/tls/certs/localhost.pem
sudo update-ca-trust
rm localhost.crt

有关详细信息,请参阅此 GitHub 注释

使用其他发行版信任证书

请参阅此 GitHub 问题

信任来自适用于 Linux 的 Windows 子系统的 HTTPS 证书

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

  • 将开发人员证书导出到 Windows 上的文件:

    dotnet dev-certs https -ep C:\<<path-to-folder>>\aspnetcore.pfx -p $CREDENTIAL_PLACEHOLDER$
    

    其中 $CREDENTIAL_PLACEHOLDER$ 是密码。

  • 在 WSL 窗口中,将导出的证书导入 WSL 实例:

    dotnet dev-certs https --clean --import /mnt/c/<<path-to-folder>>/aspnetcore.pfx -p $CREDENTIAL_PLACEHOLDER$
    

上述方法是按每个证书和每个 WSL 发行版进行的一次性操作。 这比反复导出证书更容易。 如果在 Windows 上更新或重新生成证书,则可能需要再次运行上述命令。

排查证书问题,例如证书不受信任

如果 ASP.NET Core HTTPS 开发证书已安装且受信任,但仍收到证书不受信任的浏览器警告,则本部分可提供帮助。 ASP.NET Core HTTPS 开发证书由 Kestrel 使用。

若要修复 IIS Express 证书,请参阅此 Stackoverflow 问题。

所有平台 - 证书不受信任

运行以下命令:

dotnet dev-certs https --clean
dotnet dev-certs https --trust

关闭打开的任何浏览器实例。 打开应用的新浏览器窗口。 证书信任由浏览器缓存。

dotnet dev-certs https --clean 失败

上述命令可解决大多数浏览器信任问题。 如果浏览器仍不信任证书,请按照以下特定于该平台的建议操作。

Docker - 证书不受信任

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

Windows - 证书不受信任

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

关闭打开的任何浏览器实例。 打开应用的新浏览器窗口。 证书信任由浏览器缓存。

OS X - 证书不受信任

  • 打开“密钥链访问”。
  • 选择“系统密钥链”。
  • 检查是否存在 localhost 证书。
  • 检查其图标上是否包含 + 符号,以表明它对于所有用户而言均受信任。
  • 从系统密钥链中删除证书。
  • 运行以下命令:
dotnet dev-certs https --clean
dotnet dev-certs https --trust

关闭打开的任何浏览器实例。 打开应用的新浏览器窗口。 证书信任由浏览器缓存。

若要排查 Visual Studio 的证书问题,请参阅使用 IIS Express 时出现 HTTPS 错误 (dotnet/AspNetCore #16892)

Linux 证书不受信任

检查配置为信任的证书是否为 Kestrel 服务器将使用的用户 HTTPS 开发人员证书。

在以下位置检查当前用户默认的 HTTPS 开发人员 Kestrel 证书:

ls -la ~/.dotnet/corefx/cryptography/x509stores/my

HTTPS 开发人员 Kestrel 证书文件是 SHA1 指纹。 当通过 dotnet dev-certs https --clean 删除该文件时,会根据需要使用不同的指纹重新生成。 使用以下命令检查导出证书的指纹是否匹配:

openssl x509 -noout -fingerprint -sha1 -inform pem -in /usr/local/share/ca-certificates/aspnet/https.crt

如果该证书不匹配,则可能是以下情况之一:

  • 旧证书。
  • 为根用户导出了开发人员证书。 对于这种情况,请导出证书。

可在以下位置检查根用户证书:

ls -la /root/.dotnet/corefx/cryptography/x509stores/my

将 IIS Express SSL 证书与 Visual Studio 一起使用

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

其他信息