强制实施 HTTPS 在 ASP.NET Core

作者:Rick Anderson

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

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

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

警告

API 项目

不要接收敏感信息的 Web Api 使用RequireHttpsAttribute RequireHttpsAttribute 使用 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

下面的代码调用 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();
    });
}
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中添加顶级条目:

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

  • 设置 "https_port主机" 设置

    • 在 "主机配置" 中。

    • 通过设置 ASPNETCORE_HTTPS_PORT 环境变量。

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

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

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

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

备注

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

Edge 部署

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

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

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

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

部署方案

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

如果在反向代理配置中转发请求,请在调用 HTTPS 重定向中间件前使用转发的标头中间件 转发的标头中间件使用 X-Forwarded-Proto 标头更新 Request.Scheme 中间件允许重定向 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 = StatusCodes.Status307TemporaryRedirect;
        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 = StatusCodes.Status307TemporaryRedirect;
        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 = StatusCodes.Status308PermanentRedirect;
            options.HttpsPort = 443;
        });
    }
}

Startup.cs中配置服务时:

public void ConfigureServices(IServiceCollection services)
{
    // IHostingEnvironment (stored in _env) is injected into the Startup class.
    if (!_env.IsDevelopment())
    {
        services.AddHttpsRedirection(options =>
        {
            options.RedirectStatusCode = StatusCodes.Status308PermanentRedirect;
            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 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();
}

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

对于第一次实现 HTTPS 的生产环境,请使用 TimeSpan 方法之一将初始HstsOptions设置为较小的值。 将值从小时设置为不超过一天,以防需要将 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 = StatusCodes.Status307TemporaryRedirect;
        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 = StatusCodes.Status307TemporaryRedirect;
        options.HttpsPort = 5001;
    });
}
  • 设置 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/HSTS

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

选择退出 HTTPS/HSTS:

信任 Windows 和 macOS 上的 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

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

dotnet dev-certs https --help

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

请参阅此 GitHub 问题

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

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

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

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

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

排查证书问题

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

所有平台-证书不受信任

运行以下命令:

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-证书不受信任

  • 检查证书存储区中的证书。 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 (dotnet/AspNetCore #16892)进行 HTTPS 错误

用于 Visual Studio 的 IIS Express SSL 证书

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

其他信息

上一篇:ASP.NET Core 安全性概述

下一篇:通过 HTTPS 在 Docker 上宿主 ASP.NET Core 映像

关注微信小程序
程序员编程王-随时随地学编程

扫描二维码
程序员编程王

扫一扫关注最新编程教程