使用 ssl 和客户端证书 (uploadReadAheadSize) 时上传大文件,但不希望预读所有数据

Posted

技术标签:

【中文标题】使用 ssl 和客户端证书 (uploadReadAheadSize) 时上传大文件,但不希望预读所有数据【英文标题】:Large file upload when using ssl and client certificates (uploadReadAheadSize) but dont want all data to be readahead 【发布时间】:2014-01-25 05:57:42 【问题描述】:

我试图搜索互联网/堆栈溢出,但找不到任何适合我的相关答案。

我有一个 asp.net web api2 应用程序(仅使用 ssl)。 我正在尝试允许大文件上传(最多 ~36mb),但除非我将 uploadReadAheadSize 更改为预读这个大小,否则我会从 IIS 收到一个错误,即请求太长。

我不想设置该属性,因为这样我的数据流只有在 IIS 已经全部读取后才会到达。

我的问题是:如何在没有配置大的 uploadreadaheadsize 的情况下使用托管的 asp.net 并使用 ssl(!) 和 web api 2 进行大文件上传?因为看起来我采取的所有步骤都不够。

上传ReadAheadSize:

指定 Web 服务器将读入缓冲区并传递给 ISAPI 扩展或模块的字节数。每个客户端请求都会发生一次。 ISAPI 扩展或模块直接从客户端接收任何附加数据。该值必须介于 0 和 2147483647 之间。 默认值为 49152。

如果我没有设置 uploadReadAheadSize 并尝试通过 ssl 上传大文件,这是我得到的错误:

HTTP 错误 413.0 - 请求实体太大

您可以尝试的事情: 由于请求实体太大,页面未显示。

最可能的原因:

Web 服务器拒绝为请求提供服务,因为请求实体太大。 Web 服务器无法为请求提供服务,因为它正在尝试协商客户端证书,但请求实体太大。 请求 URL 或 URL 的物理映射(即 URL 内容的物理文件系统路径)太长。 你可以尝试的事情: 验证请求是否有效。 如果使用客户端证书,请尝试:

增加 system.webServer/serverRuntime@uploadReadAheadSize

配置您的 SSL 端点以协商客户端证书作为初始 SSL 握手的一部分。 (netsh http 添加 sslcert ... clientcertnegotiation=enable)

Verify that the request is valid.
  If using client certificates, try:
    Increasing system.webServer/serverRuntime@uploadReadAheadSize
    Configure your SSL endpoint to negotiate client certificates as part of the initial SSL handshake. (netsh http add sslcert ... clientcertnegotiation=enable)

如果我将预读配置为我想要允许的大小,iis 会允许我的请求:

C:\Windows\SysWOW64>C:\Windows\System32\inetsrv\appcmd set config ... -section:system.webServer/serverRuntime /uploadReadAheadSize:n /commit:apphost
Applied configuration changes to section "system.webServer/serverRuntime" for "MACHINE/WEBROOT/APPHOST/..." at configuration commit path "MACHINE/WEBROOT/APPHOST"

我在 web.config 中配置了这个:

...
<httpRuntime targetFramework="4.5.1" maxRequestLength="36864"  /> 
...

...
<system.webServer>
    <security>
      <requestFiltering>
        <requestLimits maxAllowedContentLength="37748736"> 
...

我有一个接收文件的虚拟控制器

[ControllerBufferlessAttribute()]
public class UploadController : ApiController

    public HttpResponseMessage Post([FromUri]string filename)
    
        var selector = RequestContext.Configuration.Services.GetHostBufferPolicySelector();
            var isbufferless = string.Format("It is 0 that i'm bufferless but still IIS already read all the data before this context because of the readahead", selector is PolicySelectorBufferless);
            return new HttpResponseMessage(HttpStatusCode.InternalServerError)  ReasonPhrase = isbufferless ;          
    

属性和策略:

public class ControllerBufferlessAttribute : Attribute, IControllerConfiguration

    public void Initialize(HttpControllerSettings settings,
        HttpControllerDescriptor descriptor)
    
        settings.Services.Replace(typeof(IHostBufferPolicySelector), new PolicySelectorBufferless());
    

public class PolicySelectorBufferless : WebHostBufferPolicySelector

    public override bool UseBufferedInputStream(object hostContext)
    
        return false;
    
    public override bool UseBufferedOutputStream(HttpResponseMessage response)
    
        return base.UseBufferedOutputStream(response);
    

我在请求中得到的内容

确实,我是无缓冲的,但由于预读,IIS 仍然已经读取了此上下文之前的所有数据

【问题讨论】:

【参考方案1】:

要使用 requestLimits 功能,您需要先set it up on IIS 级别。

也许您一开始就忘记在您的 IIS 服务器上安装请求过滤。

HTH

【讨论】:

【参考方案2】:

Make IIS require SSL client certificate during initial handshake。然后你的 maxRequestLength="" 配置就会启动。

【讨论】:

这个链接应该是什么?

以上是关于使用 ssl 和客户端证书 (uploadReadAheadSize) 时上传大文件,但不希望预读所有数据的主要内容,如果未能解决你的问题,请参考以下文章

国密证书双向认证客户端发送哪个

要求 SSL 证书和客户端证书在 WCF JSON 服务中引发异常

求助delphi实现ssl验证客户端证书

使用客户端证书和 Android 的 HttpsURLConnection 通过 SSL 上传文件

wcf 服务服务器和客户端证书与 Ssl 证书不同时的安全异常

nginx和iis下的SSL双向认证教程【ca 自签 ssl证书】