ASP.NET Core 中的 HTTP.sys Web 服务器实现HTTP.sys web server implementation in ASP.NET Core

作者:Tom DykstraChris RossLuke LathamBy Tom Dykstra, Chris Ross, and Luke Latham

HTTP.sys 是仅在 Windows 上运行的适用于 ASP.NET Core 的 Web 服务器HTTP.sys is a web server for ASP.NET Core that only runs on Windows. HTTP.sys 是 Kestrel 服务器的替代选择,提供了一些 Kestrel 不提供的功能。HTTP.sys is an alternative to Kestrel server and offers some features that Kestrel doesn't provide.

重要

HTTP.sys 与 ASP.NET Core 模块不兼容,无法与 IIS 或 IIS Express 结合使用。HTTP.sys isn't compatible with the ASP.NET Core Module and can't be used with IIS or IIS Express.

HTTP.sys 支持以下功能:HTTP.sys supports the following features:

  • Windows 身份验证Windows Authentication
  • 端口共享Port sharing
  • 具有 SNI 的 HTTPSHTTPS with SNI
  • 基于 TLS 的 HTTP/2(Windows 10 或更高版本)HTTP/2 over TLS (Windows 10 or later)
  • 直接文件传输Direct file transmission
  • 响应缓存Response caching
  • WebSocket(Windows 8 或更高版本)WebSockets (Windows 8 or later)

受支持的 Windows 版本:Supported Windows versions:

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

查看或下载示例代码如何下载View or download sample code (how to download)

何时使用 HTTP.sysWhen to use HTTP.sys

HTTP.sys 对于以下情形的部署来说很有用:HTTP.sys is useful for deployments where:

  • 需要将服务器直接公开到 Internet 而不使用 IIS 的部署。There's a need to expose the server directly to the Internet without using IIS.

    HTTP.sys 直接与 Internet 进行通信

  • 内部部署需要 Kestrel 中没有的功能,如 Windows 身份验证An internal deployment requires a feature not available in Kestrel, such as Windows Authentication.

    HTTP.sys 直接与内部网络进行通信

HTTP.sys 是一项成熟的技术,可以抵御多种攻击,并提供可靠、安全、可伸缩的全功能 Web 服务器。HTTP.sys is mature technology that protects against many types of attacks and provides the robustness, security, and scalability of a full-featured web server. IIS 本身作为 HTTP.sys 之上的 HTTP 侦听器运行。IIS itself runs as an HTTP listener on top of HTTP.sys.

HTTP/2 支持HTTP/2 support

如果满足以下基本要求,将为 ASP.NET Core 应用启用 HTTP/2HTTP/2 is enabled for ASP.NET Core apps if the following base requirements are met:

如果已建立 HTTP/2 连接,HttpRequest.Protocol 会报告 HTTP/2If an HTTP/2 connection is established, HttpRequest.Protocol reports HTTP/2.

如果已建立 HTTP/2 连接,HttpRequest.Protocol 会报告 HTTP/1.1If an HTTP/2 connection is established, HttpRequest.Protocol reports HTTP/1.1.

默认情况下将启用 HTTP/2。HTTP/2 is enabled by default. 如果未建立 HTTP/2 连接,连接会回退到 HTTP/1.1。If an HTTP/2 connection isn't established, the connection falls back to HTTP/1.1. 在 Windows 的未来版本中,将提供 HTTP/2 配置标志,包括使用 HTTP.sys 禁用 HTTP/2 的功能。In a future release of Windows, HTTP/2 configuration flags will be available, including the ability to disable HTTP/2 with HTTP.sys.

对 Kerberos 进行内核模式身份验证Kernel mode authentication with Kerberos

HTTP.sys 通过 Kerberos 身份验证协议委托给内核模式身份验证。HTTP.sys delegates to kernel mode authentication with the Kerberos authentication protocol. Kerberos 和 HTTP.sys 不支持用户模式身份验证。User mode authentication isn't supported with Kerberos and HTTP.sys. 必须使用计算机帐户来解密从 Active Directory 获取的并由客户端转发到服务器的 Kerberos 令牌/票证,以便对用户进行身份验证。The machine account must be used to decrypt the Kerberos token/ticket that's obtained from Active Directory and forwarded by the client to the server to authenticate the user. 注册主机的服务主体名称 (SPN),而不是应用的用户。Register the Service Principal Name (SPN) for the host, not the user of the app.

如何使用 HTTP.sysHow to use HTTP.sys

配置 ASP.NET Core 应用以使用 HTTP.sysConfigure the ASP.NET Core app to use HTTP.sys

  1. 使用 Microsoft.AspNetCore.App metapackage (nuget.org)(ASP.NET Core 2.1 或更高版本)时,不需要项目文件中的包引用。A package reference in the project file isn't required when using the Microsoft.AspNetCore.App metapackage (nuget.org) (ASP.NET Core 2.1 or later). 未使用 Microsoft.AspNetCore.App 元包时,向 Microsoft.AspNetCore.Server.HttpSys 添加包引用。When not using the Microsoft.AspNetCore.App metapackage, add a package reference to Microsoft.AspNetCore.Server.HttpSys.

  2. 生成 Web 主机时调用 UseHttpSys 扩展方法,同时指定所需的 HttpSysOptionsCall the UseHttpSys extension method when building Web Host, specifying any required 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 配置。Additional HTTP.sys configuration is handled through registry settings.

    HTTP.sys 选项HTTP.sys options

    PropertyProperty 说明Description 默认Default
    AllowSynchronousIOAllowSynchronousIO 控制是否允许 HttpContext.Request.BodyHttpContext.Response.Body 的同步输入/输出。Control whether synchronous input/output is allowed for the HttpContext.Request.Body and HttpContext.Response.Body. true
    Authentication.AllowAnonymousAuthentication.AllowAnonymous 允许匿名请求。Allow anonymous requests. true
    Authentication.SchemesAuthentication.Schemes 指定允许的身份验证方案。Specify the allowed authentication schemes. 可能在处理侦听器之前随时修改。May be modified at any time prior to disposing the listener. 通过 AuthenticationSchemes 枚举 BasicKerberosNegotiateNoneNTLM 提供值。Values are provided by the AuthenticationSchemes enum: Basic, Kerberos, Negotiate, None, and NTLM. None
    EnableResponseCachingEnableResponseCaching 尝试内核模式缓存,响应合格的标头。Attempt kernel-mode caching for responses with eligible headers. 该响应可能不包括 Set-CookieVaryPragma 标头。The response may not include Set-Cookie, Vary, or Pragma headers. 它必须包括属性为 publicCache-Control 标头和 shared-max-agemax-age 值,或 Expires 标头。It must include a Cache-Control header that's public and either a shared-max-age or max-age value, or an Expires header. true
    MaxAccepts 最大并发接受数量。The maximum number of concurrent accepts. 5 × 环境。
    ProcessorCount
    5 × Environment.
    ProcessorCount
    MaxConnections 要接受的最大并发连接数。The maximum number of concurrent connections to accept. 使用 -1 实现无限。Use -1 for infinite. 通过 null 使用注册表的计算机范围内的设置。Use null to use the registry's machine-wide setting. null
    (无限制)(unlimited)
    MaxRequestBodySize 请参阅 MaxRequestBodySize 部分。See the MaxRequestBodySize section. 30000000 个字节30000000 bytes
    (~28.6 MB)(~28.6 MB)
    RequestQueueLimit 队列中允许的最大请求数。The maximum number of requests that can be queued. 10001000
    ThrowWriteExceptions 指示由于客户端断开连接而失败的响应主体写入应引发异常还是正常完成。Indicate if response body writes that fail due to client disconnects should throw exceptions or complete normally. false
    (正常完成)(complete normally)
    Timeouts 公开 HTTP.sys TimeoutManager 配置,也可以在注册表中进行配置。Expose the HTTP.sys TimeoutManager configuration, which may also be configured in the registry. 请访问 API 链接详细了解每个设置,包括默认值:Follow the API links to learn more about each setting, including default values:
    UrlPrefixes 指定要向 HTTP.sys 注册的 UrlPrefixCollectionSpecify the UrlPrefixCollection to register with HTTP.sys. 最有用的是 UrlPrefixCollection.Add,它用于将前缀添加到集合中。The most useful is UrlPrefixCollection.Add, which is used to add a prefix to the collection. 可能在处理侦听器之前随时对这些设置进行修改。These may be modified at any time prior to disposing the listener.

    MaxRequestBodySizeMaxRequestBodySize

    允许的请求正文的最大大小(以字节计)。The maximum allowed size of any request body in bytes. 当设置为 null 时,最大请求正文大小不受限制。When set to null, the maximum request body size is unlimited. 此限制不会影响升级后的连接,这始终不受限制。This limit has no effect on upgraded connections, which are always unlimited.

    在 ASP.NET Core MVC 应用中为单个 IActionResult 替代限制的推荐方法是在操作方法上使用 RequestSizeLimitAttribute 属性:The recommended method to override the limit in an ASP.NET Core MVC app for a single IActionResult is to use the RequestSizeLimitAttribute attribute on an action method:

    [RequestSizeLimit(100000000)]
    public IActionResult MyActionMethod()
    

    如果在应用开始读取请求后尝试配置请求限制,则会引发异常。An exception is thrown if the app attempts to configure the limit on a request after the app has started reading the request. IsReadOnly 属性可用于指示 MaxRequestBodySize 属性是否处于只读状态。只读状态意味着已经太迟了,无法配置限制。An IsReadOnly property can be used to indicate if the MaxRequestBodySize property is in a read-only state, meaning it's too late to configure the limit.

    如果应用应替代每个请求的 MaxRequestBodySize,请使用 IHttpMaxRequestBodySizeFeatureIf the app should override MaxRequestBodySize per-request, use the 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();
    }
    
  3. 如果使用的是 Visual Studio,请确保应用未经配置以运行 IIS 或 IIS Express。If using Visual Studio, make sure the app isn't configured to run IIS or IIS Express.

    在 Visual Studio 中,默认启动配置文件是针对 IIS Express 的。In Visual Studio, the default launch profile is for IIS Express. 若要作为控制台应用运行该项目,请手动更改所选配置文件,如以下屏幕截图中所示:To run the project as a console app, manually change the selected profile, as shown in the following screen shot:

    选择控制台应用配置文件

配置 Windows ServerConfigure Windows Server

  1. 确定要为应用打开的端口,并使用 Windows 防火墙New-NetFirewallRule PowerShell cmdlet 打开防火墙端口,以允许流量到达 HTTP.sys。Determine the ports to open for the app and use Windows Firewall or the New-NetFirewallRule PowerShell cmdlet to open firewall ports to allow traffic to reach HTTP.sys. 在以下命令和应用配置中,使用的是端口 443。In the following commands and app configuration, port 443 is used.

  2. 在部署到 Azure VM 时,在网络安全组中打开端口。When deploying to an Azure VM, open the ports in the Network Security Group. 在以下命令和应用配置中,使用的是端口 443。In the following commands and app configuration, port 443 is used.

  3. 如果需要,获取并安装 X.509 证书。Obtain and install X.509 certificates, if required.

    在 Windows 上,可使用 New-SelfSignedCertificate PowerShell cmdlet 创建自签名证书。On Windows, create self-signed certificates using the New-SelfSignedCertificate PowerShell cmdlet. 有关不支持的示例,请参阅 UpdateIISExpressSSLForChrome.ps1For an unsupported example, see UpdateIISExpressSSLForChrome.ps1.

    在服务器的“本地计算机” > “个人” 存储中,安装自签名证书或 CA 签名证书。Install either self-signed or CA-signed certificates in the server's Local Machine > Personal store.

  4. 如果应用为框架相关部署,则安装 .NET Core、.NET Framework 或两者(如果应用是面向 .NET Framework 的 .NET Core 应用)。If the app is a framework-dependent deployment, install .NET Core, .NET Framework, or both (if the app is a .NET Core app targeting the .NET Framework).

    • .NET Core – 如果应用需要 .NET Core,请从 .NET Core 下载页获取并运行 .NET Core 运行时 安装程序。.NET Core – If the app requires .NET Core, obtain and run the .NET Core Runtime installer from .NET Core Downloads. 请勿在服务器上安装完整 SDK。Don't install the full SDK on the server.
    • .NET Framework – 如果应用需要 .NET Framework,请参阅 .NET Framework 安装指南.NET Framework – If the app requires .NET Framework, see the .NET Framework installation guide. 安装所需的 .NET Framework。Install the required .NET Framework. 可以从 .NET Core 下载页获取最新 .NET Framework 的安装程序。The installer for the latest .NET Framework is available from the .NET Core Downloads page.

    如果应用是独立式部署,应用在部署中包含运行时。If the app is a self-contained deployment, the app includes the runtime in its deployment. 无需在服务器上安装任何框架。No framework installation is required on the server.

  5. 在应用中配置 URL 和端口。Configure URLs and ports in the app.

    默认情况下,ASP.NET Core 绑定到 http://localhost:5000By default, ASP.NET Core binds to http://localhost:5000. 若要配置 URL 前缀和端口,可采用以下方法:To configure URL prefixes and ports, options include:

    • UseUrls
    • urls 命令行参数urls command-line argument
    • ASPNETCORE_URLS 环境变量ASPNETCORE_URLS environment variable
    • UrlPrefixes

    下面的代码示例展示了如何对端口 443 结合使用 UrlPrefixes 和服务器的本地 IP 地址 10.0.0.4The following code example shows how to use UrlPrefixes with the server's local IP address 10.0.0.4 on port 443:

    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 的一个优点是会为格式不正确的前缀立即生成一条错误消息。An advantage of UrlPrefixes is that an error message is generated immediately for improperly formatted prefixes.

    UrlPrefixes 中的设置替代 UseUrls/urls/ASPNETCORE_URLS 设置。The settings in UrlPrefixes override UseUrls/urls/ASPNETCORE_URLS settings. 因此,UseUrlsurlsASPNETCORE_URLS 环境变量的一个优点是在 Kestrel 和 HTTP.sys 之间切换变得更加容易。Therefore, an advantage of UseUrls, urls, and the ASPNETCORE_URLS environment variable is that it's easier to switch between Kestrel and HTTP.sys. 有关更多信息,请参见ASP.NET Core Web 主机For more information, see ASP.NET Core Web 主机.

    HTTP.sys 使用 HTTP 服务器 API UrlPrefix 字符串格式HTTP.sys uses the HTTP Server API UrlPrefix string formats.

    警告

    不应使用顶级通配符绑定(http://*:80/http://+:80) 。Top-level wildcard bindings (http://*:80/ and http://+:80) should not be used. 顶级通配符绑定会带来应用安全漏洞。Top-level wildcard bindings create app security vulnerabilities. 此行为同时适用于强通配符和弱通配符。This applies to both strong and weak wildcards. 请使用显式主机名或 IP 地址,而不是通配符。Use explicit host names or IP addresses rather than wildcards. 如果可控制整个父域(相对于易受攻击的 *.com),子域通配符绑定(例如,*.mysub.com)不会构成安全风险。Subdomain wildcard binding (for example, *.mysub.com) isn't a security risk if you control the entire parent domain (as opposed to *.com, which is vulnerable). 有关详细信息,请参阅 RFC 7230:第 5.4 节:主机For more information, see RFC 7230: Section 5.4: Host.

  6. 在服务器上预注册 URL 前缀。Preregister URL prefixes on the server.

    用于配置 HTTP.sys 的内置工具为 netsh.exeThe built-in tool for configuring HTTP.sys is netsh.exe. netsh.exe 用于保留 URL 前缀并分配 X.509 证书。netsh.exe is used to reserve URL prefixes and assign X.509 certificates. 此工具需要管理员特权。The tool requires administrator privileges.

    使用 netsh.exe 工具为应用注册 URL:Use the netsh.exe tool to register URLs for the app:

    netsh http add urlacl url=<URL> user=<USER>
    
    • <URL> – 完全限定的统一资源定位器 (URL)。<URL> – The fully qualified Uniform Resource Locator (URL). 不要使用通配符绑定。Don't use a wildcard binding. 请使用有效主机名或本地 IP 地址。Use a valid hostname or local IP address. URL 必须包含尾部反斜杠。 The URL must include a trailing slash.
    • <USER> – 指定用户名或用户组名称。<USER> – Specifies the user or user-group name.

    在以下示例中,服务器的本地 IP 地址是 10.0.0.4In the following example, the local IP address of the server is 10.0.0.4:

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

    在 URL 注册后,工具响应返回 URL reservation successfully addedWhen a URL is registered, the tool responds with URL reservation successfully added.

    若要删除已注册的 URL,请使用 delete urlacl 命令:To delete a registered URL, use the delete urlacl command:

    netsh http delete urlacl url=<URL>
    
  7. 在服务器上注册 X.509 证书。Register X.509 certificates on the server.

    使用 netsh.exe 工具为应用注册证书:Use the netsh.exe tool to register certificates for the app:

    netsh http add sslcert ipport=<IP>:<PORT> certhash=<THUMBPRINT> appid="{<GUID>}"
    
    • <IP> – 指定绑定的本地 IP 地址。<IP> – Specifies the local IP address for the binding. 不要使用通配符绑定。Don't use a wildcard binding. 请使用有效 IP 地址。Use a valid IP address.
    • <PORT> – 指定绑定的端口。<PORT> – Specifies the port for the binding.
    • <THUMBPRINT> – X.509 证书指纹。<THUMBPRINT> – The X.509 certificate thumbprint.
    • <GUID> – 开发人员生成的表示应用的 GUID,以供参考。<GUID> – A developer-generated GUID to represent the app for informational purposes.

    为了便于参考,将 GUID 作为包标记存储在应用中:For reference purposes, store the GUID in the app as a package tag:

    • 在 Visual Studio 中:In Visual Studio:
      • 在“解决方案资源管理器” 中,右键单击应用,并选择“属性” ,以打开应用的项目属性。Open the app's project properties by right-clicking on the app in Solution Explorer and selecting Properties.
      • 选择“包” 选项卡。Select the Package tab.
      • 在“标记” 字段中输入已创建的 GUID。Enter the GUID that you created in the Tags field.
    • 如果使用的不是 Visual Studio:When not using Visual Studio:
      • 打开应用的项目文件。Open the app's project file.

      • 使用已创建的 GUID,将 <PackageTags> 属性添加到新的或现有的 <PropertyGroup>Add a <PackageTags> property to a new or existing <PropertyGroup> with the GUID that you created:

        <PropertyGroup>
          <PackageTags>9412ee86-c21b-4eb8-bd89-f650fbf44931</PackageTags>
        </PropertyGroup>
        

    如下示例中:In the following example:

    • 服务器的本地 IP 地址是 10.0.0.4The local IP address of the server is 10.0.0.4.
    • 联机随机 GUID 生成器提供 appid 值。An online random GUID generator provides the appid value.
    netsh http add sslcert 
        ipport=10.0.0.4:443 
        certhash=b66ee04419d4ee37464ab8785ff02449980eae10 
        appid="{9412ee86-c21b-4eb8-bd89-f650fbf44931}"
    

    在证书注册后,工具响应返回 SSL Certificate successfully addedWhen a certificate is registered, the tool responds with SSL Certificate successfully added.

    若要删除证书注册,请使用 delete sslcert 命令:To delete a certificate registration, use the delete sslcert command:

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

    netsh.exe 的参考文档:Reference documentation for netsh.exe:

  8. 运行应用。Run the app.

    结合使用 HTTP(而不是 HTTPS)和大于 1024 的端口号绑定到 localhost,无需管理员权限,即可运行应用。Administrator privileges aren't required to run the app when binding to localhost using HTTP (not HTTPS) with a port number greater than 1024. 对于其他配置(例如,使用本地 IP 地址或绑定到端口 443),必须有管理员权限才能运行应用。For other configurations (for example, using a local IP address or binding to port 443), run the app with administrator privileges.

    应用在服务器的公共 IP 地址处响应。The app responds at the server's public IP address. 此示例在 Internet 上的公共 IP 地址 104.214.79.47 处访问服务器。In this example, the server is reached from the Internet at its public IP address of 104.214.79.47.

    此示例使用的是开发证书。A development certificate is used in this example. 在绕过浏览器的不受信任证书警告后,页面安全加载。The page loads securely after bypassing the browser's untrusted certificate warning.

    显示应用索引页已加载的浏览器窗口

代理服务器和负载均衡器方案Proxy server and load balancer scenarios

如果应用由 HTTP.sys 托管并且与来自 Internet 或公司网络的请求进行交互,当在代理服务器和负载均衡器后托管时,可能需要其他配置。For apps hosted by HTTP.sys that interact with requests from the Internet or a corporate network, additional configuration might be required when hosting behind proxy servers and load balancers. 有关详细信息,请参阅配置 ASP.NET Core 以使用代理服务器和负载均衡器For more information, see Configure ASP.NET Core to work with proxy servers and load balancers.

其他资源Additional resources