在 ASP.NET Core 强制实施 HTTPS

作者:Rick Anderson

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

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

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

警告

API 项目

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

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

HSTS 和 API 项目

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

警告

API 项目

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

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

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

以下代码在 UseHttpsRedirection 类中 Startup 调用 :

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();
    });
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Error");
        app.UseHsts();
    }

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

    app.UseMvc();
}

前面突出显示的代码:

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

端口配置

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

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

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

  • 设置 https_port 主机设置

    • 在 "主机配置" 中。

    • 通过设置 ASPNETCORE_HTTPS_PORT 环境变量。

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

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

  • 设置 https_port 主机设置

    • 在 "主机配置" 中。

    • 通过设置 ASPNETCORE_HTTPS_PORT 环境变量。

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

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

  • 在开发中,在 上的launchsettings.js HTTPS URL。 使用 HTTPS 时IIS Express HTTPS。

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

备注

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

Edge 部署

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

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

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

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

部署方案

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

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

部署到 Azure App Service 时,请按照 教程:将现有的自定义 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;
    });
}
public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();

    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;
    });
}

AddHttpsRedirection只有在更改或的值时,才需要调用 HttpsPort RedirectStatusCode

前面突出显示的代码:

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

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

启动 时配置服务时:

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;
        });
    }
}

启动 时配置服务时:

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

HTTPS 重定向中间件备用方法

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

在不需要其他重定向规则的情况下重定向到 HTTPS 时,我们建议使用 HTTPS 重定向中间件 (UseHttpsRedirection 本主题中所述) 。

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

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

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

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

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

ASP.NET Core 2.1 及更高版本使用 扩展方法实现 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();
    });
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Error");
        app.UseHsts();
    }

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

    app.UseMvc();
}

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

对于首次实现 HTTPS 的生产环境,使用方法之一将初始 HstsOptions.MaxAge 设置为较小的 TimeSpan 值。 在需要将 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;
    });
}
public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();

    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 策略应用于主机子域。
  • max-age 标头的参数显式设置 Strict-Transport-Security 为60天。 如果未设置,则默认值为30天。 有关详细信息,请参阅 最大期限指令
  • 添加 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 Core Web 应用程序 "对话框,其中显示未选择" 配置为 HTTPS "复选框。

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

信任 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

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

dotnet dev-certs https --help

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

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

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

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

在 上创建策略文件:

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

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

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

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

按照 security.enterprise_roots.enabled = true 以下说明进行设置:

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

有关详细信息,请参阅 在 Firefox 中 (CAs) 设置证书颁发机构mozilla/策略模板/自述文件

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

请参阅此 GitHub 问题

Ubuntu 信任证书进行服务间通信

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

  2. 运行以下命令:

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

上述命令中的路径专用于 Ubuntu。 对于其他分发版,请选择适当的路径,或使用证书颁发机构 (Ca) 的路径。

在 Linux 上信任 HTTPS 证书

建立信任是特定于浏览器的。 以下各节提供了 Chromium 浏览器边缘、Chrome 和 Firefox 的说明。

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

对于 Linux 上的 chromium 浏览器:

  • libnss3-tools为分发安装。

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

  • 将证书导出到以下命令:

    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
    certutil -d sql:$HOME/.pki/nssdb -A -t "C,," -n localhost -i /usr/local/share/ca-certificates/  aspnet/https.crt
    
  • 退出并重新启动浏览器。

在 Linux 上通过 Firefox 信任证书

  • 将证书导出到以下命令:

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

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

  • 在 创建包含以下内容的 JSON /usr/lib/firefox/distribution/policies.json 文件:

    {
        "policies": {
            "Certificates": {
                "Install": [
                    "/usr/local/share/ca-certificates/aspnet/https.crt"
                ]
            }
        }
    }
    

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

信任 Fedora 34 的证书

请参阅 此 GitHub 注释

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

WSL 适用于 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

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

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

Docker-证书不受信任

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

Windows-证书不受信任

  • 检查证书存储区中的证书。 localhost在和中应有一个具有 ASP.NET Core HTTPS development certificate 友好名称的证书 Current User > Personal > Certificates``Current User > Trusted root certification authorities > Certificates
  • 从 "个人" 和 "受信任的根证书颁发机构" 中删除所有找到的证书。 请勿 删除 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

关闭打开的任何浏览器实例。 打开应用的新浏览器窗口。

请参阅 使用 dotnet/AspNetCore IIS Express (HTTPS 错误#16892) 以排查与 Visual Studio。

IIS Express一起使用的 SSL Visual Studio

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

其他信息