ASP.NET Core 託管和部署(二)【HTTP.sys】

風靈使發表於2019-02-20

ASP.NET Core 中的 HTTP.sys Web 伺服器實現

HTTP.sys 是僅在 Windows 上執行的適用於 ASP.NET Core 的 Web 伺服器HTTP.sysKestrel 伺服器的替代選擇,提供了一些 Kestrel 不提供的功能。

重要
HTTP.sys 與 ASP.NET Core 模組不相容,無法與 IIS 或 IIS Express 結合使用。

HTTP.sys 支援以下功能:

  • Windows 身份驗證
  • 埠共享
  • 具有 SNI 的 HTTPS
  • 基於 TLS 的 HTTP/2(Windows 10 或更高版本)
  • 直接檔案傳輸
  • 響應快取
  • WebSocket(Windows 8 或更高版本)

受支援的 Windows 版本:

  • Windows 7 或更高版本
  • Windows Server 2008 R2 或更高版本

何時使用 HTTP.sys

HTTP.sys 對於以下情形的部署來說很有用:

  • 需要將伺服器直接公開到 Internet 而不使用 IIS 的部署。

    HTTP.sys 直接與 Internet 進行通訊

  • 內部部署需要 Kestrel 中沒有的功能,如 Windows 身份驗證

    HTTP.sys 直接與內部網路進行通訊

HTTP.sys 是一項成熟的技術,可以抵禦多種攻擊,並提供可靠、安全、可伸縮的全功能 Web 伺服器。 IIS 本身作為 HTTP.sys 之上的 HTTP 偵聽器執行。

HTTP/2 支援

如果滿足以下基本要求,將為 ASP.NET Core 應用啟用 HTTP/2

如果已建立 HTTP/2 連線,HttpRequest.Protocol 會報告 HTTP/2

預設情況下將啟用 HTTP/2。 如果未建立 HTTP/2 連線,連線會回退到 HTTP/1.1。 在 Windows 的未來版本中,將提供 HTTP/2 配置標誌,包括使用 HTTP.sys 禁用 HTTP/2 的功能。

Kerberos 進行核心模式身份驗證

HTTP.sys 通過 Kerberos 身份驗證協議委託給核心模式身份驗證。 KerberosHTTP.sys 不支援使用者模式身份驗證。 必須使用計算機帳戶來解密從 Active Directory 獲取的並由客戶端轉發到伺服器的 Kerberos 令牌/票證,以便對使用者進行身份驗證。 註冊主機的服務主體名稱 (SPN),而不是應用的使用者。

如何使用 HTTP.sys

配置 ASP.NET Core 應用以使用 HTTP.sys

  1. 使用 Microsoft.AspNetCore.App metapackage (nuget.org)(ASP.NET Core 2.1 或更高版本)時,不需要專案檔案中的包引用。 未使用 Microsoft.AspNetCore.App 元包時,向 Microsoft.AspNetCore.Server.HttpSys 新增包引用。

  2. 生成 Web 主機時呼叫 UseHttpSys擴充套件方法,同時指定所需的 HttpSysOptions

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .UseHttpSys(options =>
        {
            // The following options are set to default values.
            options.Authentication.Schemes = AuthenticationSchemes.None;
            options.Authentication.AllowAnonymous = true;
            options.MaxConnections = null;
            options.MaxRequestBodySize = 30000000;
            options.UrlPrefixes.Add("http://localhost:5000");
        });

通過登錄檔設定處理其他 HTTP.sys 配置。

HTTP.sys 選項

Property 說明​​ 預設
AllowSynchronousIO 控制是否允許 HttpContext.Request.Body 和 HttpContext.Response.Body 的同步輸入/輸出。 True
Authentication.AllowAnonymous 允許匿名請求。 True
Authentication.Schemes 指定允許的身份驗證方案。 可能在處理偵聽器之前隨時修改。 通過 AuthenticationSchemes 列舉 Basic、Kerberos、Negotiate、None 和 NTLM 提供值。 None
EnableResponseCaching 嘗試核心模式快取,響應合格的標頭。 該響應可能不包括 Set-Cookie、Vary 或 Pragma 標頭。 它必須包括屬性為 public 的 Cache-Control 標頭和 shared-max-age 或 max-age 值,或 Expires 標頭。 True
MaxAccepts 最大併發接受數量。 5 × 環境。
ProcessorCount
MaxConnections 要接受的最大併發連線數。 使用 -1 實現無限。 通過 null 使用登錄檔的計算機範圍內的設定。 null
(無限制)
MaxRequestBodySize 請參閱 MaxRequestBodySize 部分。 30000000 個位元組
(~28.6 MB)
RequestQueueLimit 佇列中允許的最大請求數。 1000
ThrowWriteExceptions 指示由於客戶端斷開連線而失敗的響應主體寫入應引發異常還是正常完成。 False
(正常完成)
Timeouts 公開 HTTP.sys TimeoutManager 配置,也可以在登錄檔中進行配置。 請訪問 API 連結詳細瞭解每個設定,包括預設值:
TimeoutManager.DrainEntityBody – HTTP 伺服器 API 對保持的連線消耗實體正文的時間上限。
TimeoutManager.EntityBody – 請求實體正文到達的時間上限。
TimeoutManager.HeaderWait – HTTP 伺服器 API 分析請求頭的時間上限。
TimeoutManager.IdleConnection – 空閒連線存在的時間上限。
TimeoutManager.MinSendBytesPerSecond – 響應的最小傳送速率。
TimeoutManager.RequestQueue – 請求在被應用選擇前在請求佇列中保留的時間上限。
UrlPrefixes 指定要向 HTTP.sys 註冊的 UrlPrefixCollection。 最有用的是 UrlPrefixCollection.Add,它用於將字首新增到集合中。 可能在處理偵聽器之前隨時對這些設定進行修改。

MaxRequestBodySize

允許的請求正文的最大大小(以位元組計)。 當設定為 null 時,最大請求正文大小不受限制。 此限制不會影響升級後的連線,這始終不受限制。

ASP.NET Core MVC 應用中為單個 IActionResult 替代限制的推薦方法是在操作方法上使用 RequestSizeLimitAttribute屬性:

   [RequestSizeLimit(100000000)]
   public IActionResult MyActionMethod()

如果在應用開始讀取請求後嘗試配置請求限制,則會引發異常。 IsReadOnly 屬性可用於指示 MaxRequestBodySize 屬性是否處於只讀狀態。只讀狀態意味著已經太遲了,無法配置限制。

如果應用應替代每個請求的 MaxRequestBodySize,請使用 IHttpMaxRequestBodySizeFeature

public void Configure(IApplicationBuilder app, IHostingEnvironment env, 
    ILogger<Startup> logger, IServer server)
{
    app.Use(async (context, next) =>
    {
        context.Features.Get<IHttpMaxRequestBodySizeFeature>()
            .MaxRequestBodySize = 10 * 1024;

        var serverAddressesFeature = 
            app.ServerFeatures.Get<IServerAddressesFeature>();
        var addresses = string.Join(", ", serverAddressesFeature?.Addresses);

        logger.LogInformation($"Addresses: {addresses}");

        await next.Invoke();
    });

    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Error");
        app.UseHsts();
    }

    // Enable HTTPS Redirection Middleware when hosting the app securely.
    //app.UseHttpsRedirection();
    app.UseStaticFiles();
    app.UseCookiePolicy();
    app.UseMvc();
}
  1. 如果使用的是 Visual Studio,請確保應用未經配置以執行 IIS 或 IIS Express。

    在 Visual Studio 中,預設啟動配置檔案是針對 IIS Express 的。 若要作為控制檯應用執行該專案,請手動更改所選配置檔案,如以下螢幕截圖中所示:
    在這裡插入圖片描述

配置 Windows Server

  1. 確定要為應用開啟的埠,並使用 Windows 防火牆或 PowerShell cmdlet 開啟防火牆埠,以允許流量到達 HTTP.sys。 在部署到 Azure VM 時,在網路安全組中開啟埠。 在以下命令和應用配置中,使用的是埠 443。

  2. 如果需要,獲取並安裝 X.509 證書。

    在 Windows 上,可使用 New-SelfSignedCertificate PowerShell cmdlet 建立自簽名證書。 有關不支援的示例,請參閱 UpdateIISExpressSSLForChrome.ps1

    在伺服器的“本地計算機” > “個人”儲存中,安裝自簽名證書或 CA 簽名證書。

  3. 如果應用為框架相關部署,則安裝 .NET Core.NET Framework 或兩者(如果應用是面向 .NET Framework 的 .NET Core 應用)。

    • .NET Core – 如果應用需要 .NET Core,請從 .NET Core 下載頁獲取並執行 .NET Core 執行時安裝程式。 請勿在伺服器上安裝完整 SDK。
    • .NET Framework – 如果應用需要 .NET Framework,請參閱 .NET Framework 安裝指南。 安裝所需的 .NET Framework。 可以從 .NET Core 下載頁獲取最新 .NET Framework 的安裝程式。

    如果應用是獨立式部署,應用在部署中包含執行時。 無需在伺服器上安裝任何框架。

  4. 在應用中配置 URL 和埠。

    預設情況下,ASP.NET Core 繫結到 http://localhost:5000。 若要配置 URL 字首和埠,可採用以下方法:

    • UseUrls
    • urls 命令列引數
    • ASPNETCORE_URLS 環境變數
    • UrlPrefixes

    下面的程式碼示例展示瞭如何對埠 443 結合使用 UrlPrefixes和伺服器的本地 IP 地址 10.0.0.4

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .UseHttpSys(options =>
        {
            options.Authentication.Schemes = AuthenticationSchemes.None;
            options.Authentication.AllowAnonymous = true;
            options.MaxConnections = null;
            options.MaxRequestBodySize = 30000000;
            // Server local IP address: 10.0.0.4
            options.UrlPrefixes.Add("https://10.0.0.4:443");
        });

UrlPrefixes 的一個優點是會為格式不正確的字首立即生成一條錯誤訊息。

UrlPrefixes 中的設定替代 UseUrls/urls/ASPNETCORE_URLS 設定。 因此,UseUrlsurlsASPNETCORE_URLS 環境變數的一個優點是在 KestrelHTTP.sys 之間切換變得更加容易。 有關更多資訊,請參見ASP.NET Core Web 主機

HTTP.sys 使用 HTTP 伺服器 API UrlPrefix 字串格式

警告
不應使用頂級萬用字元繫結(http://*:80/http://+:80)。 頂級萬用字元繫結會帶來應用安全漏洞。 此行為同時適用於強萬用字元和弱萬用字元。 請使用顯式主機名或 IP 地址,而不是萬用字元。 如果可控制整個父域(相對於易受攻擊的 *.com),子域萬用字元繫結(例如,*.mysub.com)不會構成安全風險。 有關詳細資訊,請參閱 RFC 7230:第 5.4 節:主機

  1. 在伺服器上預註冊 URL 字首。

    用於配置 HTTP.sys 的內建工具為 netsh.exenetsh.exe 用於保留 URL 字首並分配 X.509 證書。 此工具需要管理員特權。

    使用 netsh.exe 工具為應用註冊 URL:

   netsh http add urlacl url=<URL> user=<USER>
  • <URL> – 完全限定的統一資源定位器 (URL)。 不要使用萬用字元繫結。 請使用有效主機名或本地 IP 地址。 URL 必須包含尾部反斜槓。
  • <USER> – 指定使用者名稱或使用者組名稱。

在以下示例中,伺服器的本地 IP 地址是 10.0.0.4

   netsh http add urlacl url=https://10.0.0.4:443/ user=Users

在 URL 註冊後,工具響應返回 URL reservation successfully added

若要刪除已註冊的 URL,請使用 delete urlacl 命令:

netsh http delete urlacl url=<URL>
  1. 在伺服器上註冊 X.509 證書。

    使用 netsh.exe 工具為應用註冊證書:

   netsh http add sslcert ipport=<IP>:<PORT> certhash=<THUMBPRINT> appid="{<GUID>}"
  • <IP> – 指定繫結的本地 IP 地址。 不要使用萬用字元繫結。 請使用有效 IP 地址。
  • <PORT> – 指定繫結的埠。
  • <THUMBPRINT> – X.509 證書指紋。
  • <GUID> – 開發人員生成的表示應用的 GUID,以供參考。

為了便於參考,將 GUID 作為包標記儲存在應用中:

  • 在 Visual Studio 中:
    • 在“解決方案資源管理器”中,右鍵單擊應用,並選擇“屬性”,以開啟應用的專案屬性。
    • 選擇“包”選項卡。
    • 在“標記”欄位中輸入已建立的 GUID。
  • 如果使用的不是 Visual Studio:
    • 開啟應用的專案檔案。
    • 使用已建立的 GUID,將 <PackageTags> 屬性新增到新的或現有的 <PropertyGroup>
       <PropertyGroup>
         <PackageTags>9412ee86-c21b-4eb8-bd89-f650fbf44931</PackageTags>
       </PropertyGroup>

如下示例中:

  • 伺服器的本地 IP 地址是 10.0.0.4
  • 聯機隨機 GUID 生成器提供 appid 值。
   netsh http add sslcert 
       ipport=10.0.0.4:443 
       certhash=b66ee04419d4ee37464ab8785ff02449980eae10 
       appid="{9412ee86-c21b-4eb8-bd89-f650fbf44931}"

在證書註冊後,工具響應返回 SSL Certificate successfully added

若要刪除證書註冊,請使用 delete sslcert 命令:

netsh http delete sslcert ipport=<IP>:<PORT>

netsh.exe 的參考文件:

  1. 執行應用。

    結合使用 HTTP(而不是 HTTPS)和大於 1024 的埠號繫結到 localhost,無需管理員許可權,即可執行應用。 對於其他配置(例如,使用本地 IP 地址或繫結到埠 443),必須有管理員許可權才能執行應用。

    應用在伺服器的公共 IP 地址處響應。 此示例在 Internet 上的公共 IP 地址 104.214.79.47 處訪問伺服器。

    此示例使用的是開發證書。 在繞過瀏覽器的不受信任證書警告後,頁面安全載入。
    在這裡插入圖片描述

代理伺服器和負載均衡器方案

如果應用由 HTTP.sys 託管並且與來自 Internet 或公司網路的請求進行互動,當在代理伺服器和負載均衡器後託管時,可能需要其他配置。 有關詳細資訊,請參閱配置 ASP.NET Core 以使用代理伺服器和負載均衡器

相關文章