【问题标题】:WCF with client certificates and "The maximum array length quota (16384) has been exceeded"带有客户端证书和“已超出最大数组长度配额 (16384)”的 WCF
【发布时间】:2014-11-13 13:16:59
【问题描述】:

我在从客户端 Web 应用程序的方法调用中向 .net 4.5 mvc wcf 应用程序中的 Web 服务发送上传的大型 Excel 文件时收到此错误。 它之前使用相同的文件,但在使用客户端证书保护客户端/服务连接后,我收到此错误

The formatter threw an exception while trying to deserialize the message: There was an error while trying to deserialize parameter http://tempuri.org/:data. The InnerException message was 'There was an error deserializing the object of type System.Byte[]. The maximum array length quota (16384) has been exceeded while reading XML data. This quota may be increased by changing the MaxArrayLength property on the XmlDictionaryReaderQuotas object used when creating the XML reader. Line 1, position 2584463.'.  Please see InnerException for more details.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.     
Exception Details: System.ServiceModel.FaultException`1[[System.ServiceModel.ExceptionDetail, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]: The formatter threw an exception while trying to deserialize the message: There was an error while trying to deserialize parameter http://tempuri.org/:data. The InnerException message was 'There was an error deserializing the object of type System.Byte[]. The maximum array length quota (16384) has been exceeded while reading XML data. This quota may be increased by changing the MaxArrayLength property on the XmlDictionaryReaderQuotas object used when creating the XML reader. Line 1, position 2584463.'.  Please see InnerException for more details.    
Source Error:    
An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.    
Stack Trace:         
[FaultException`1: The formatter threw an exception while trying to deserialize the message: There was an error while trying to deserialize parameter http://tempuri.org/:data. The InnerException message was 'There was an error deserializing the object of type System.Byte[]. The maximum array length quota (16384) has been exceeded while reading XML data. This quota may be increased by changing the MaxArrayLength property on the XmlDictionaryReaderQuotas object used when creating the XML reader. Line 1, position 2584463.'.  Please see InnerException for more details.]
   System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg) +10733331
   System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type) +336
   MyService.WebApp.ImportServiceRef.IImportService.Import(LoginContext lctx, Byte[] data, String filename) +0

在阅读了很多关于 stackoverflow 的问题后,我尝试了几种方法来增加所有绑定中的所有缓冲区和最大参数,但最终仍然得到相同的错误。奇怪的是,设置在切换到客户端证书之前有效。有什么建议么?

客户端 Web.config

<?xml version="1.0"?>
<configuration>
  <configSections>
    <section name="system.identityModel" type="System.IdentityModel.Configuration.SystemIdentityModelSection, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=..."/>
    <section name="system.identityModel.services" type="System.IdentityModel.Services.Configuration.SystemIdentityModelServicesSection, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=..."/>
  </configSections>
  <appSettings>
      ...
    </appSettings>
  <location path="FederationMetadata">
    <system.web>
      <authorization>
        <allow users="*"/>
      </authorization>
    </system.web>
  </location>
  <system.web>
    <globalization uiCulture="auto:de-DE" culture="auto:de-DE" requestEncoding="utf-8" responseEncoding="utf-8"/>
    <customErrors mode="Off" defaultRedirect="Error"/>
    <identity impersonate="false"/>
    <sessionState mode="InProc" timeout="120"/>
    <compilation debug="true" targetFramework="4.5"/>
    <httpRuntime targetFramework="4.5" requestValidationMode="4.5" maxRequestLength="2097151"/>
    <authentication mode="Windows"/>
    <authorization>
      <deny users="?"/>
    </authorization>
    <pages>
      <namespaces>
          ...
      </namespaces>
    </pages>
  </system.web>
  <system.webServer>
    <validation validateIntegratedModeConfiguration="false"/>
    <handlers>
        ...
    </handlers>
    <httpProtocol>
    </httpProtocol>
  </system.webServer>
  <runtime>
      ...
  </runtime>
  <system.serviceModel>

    <behaviors>
      <endpointBehaviors>
        <behavior name="SecuredBehaviour">
          <dataContractSerializer maxItemsInObjectGraph="2147483647"/>
          <clientCredentials>
            <clientCertificate findValue="CertAzusClientTeststage" x509FindType="FindBySubjectName" storeLocation="LocalMachine" storeName="My"/>
            <serviceCertificate>
              <authentication certificateValidationMode="PeerOrChainTrust"/>
            </serviceCertificate>
          </clientCredentials>
        </behavior>
      </endpointBehaviors>
    </behaviors>

    <bindings>
      <basicHttpBinding>
        <binding name="secureBinding" maxBufferPoolSize="2147483647" maxBufferSize="524288" maxReceivedMessageSize="2147483647">
          <security mode="Transport" />
          <readerQuotas
            maxArrayLength="2147483647"
            maxBytesPerRead="2147483647"
            maxDepth="2147483647"
            maxNameTableCharCount="2147483647"
            maxStringContentLength="2147483647" />                          
        </binding>
      </basicHttpBinding>
      <wsHttpBinding>
        <binding name="secureBindingWs" closeTimeout="00:01:00" openTimeout="00:01:00"
          receiveTimeout="00:15:00" sendTimeout="00:15:00" 
          messageEncoding="Text" textEncoding="utf-8"
          useDefaultWebProxy="true"
          maxBufferPoolSize="2147483647" maxBufferSize="524288" maxReceivedMessageSize="2147483647" 
          >
          <readerQuotas
            maxArrayLength="2147483647"
            maxBytesPerRead="2147483647"
            maxDepth="2147483647"
            maxNameTableCharCount="2147483647"
            maxStringContentLength="2147483647" />                          
        </binding>

        <binding name="wsHttpEndpointBinding" sendTimeout="12:00:00"
          maxBufferPoolSize="2147483647" maxBufferSize="524288" maxReceivedMessageSize="2147483647" 
        >
          <security mode="Message">
              <message clientCredentialType="Certificate"/>
          </security>
          <readerQuotas
            maxArrayLength="2147483647"
            maxBytesPerRead="2147483647"
            maxDepth="2147483647"
            maxNameTableCharCount="2147483647"
            maxStringContentLength="2147483647" />                          
        </binding>
      </wsHttpBinding>
    </bindings>
    <protocolMapping>
      <add binding="basicHttpBinding" scheme="https" bindingConfiguration="secureBinding"/>
      <add binding="wsHttpBinding" scheme="https" bindingConfiguration="secureBindingWs"/>
    </protocolMapping>
    <client>
      <endpoint address="http://server-xyz/Service/AntragService.svc"
        binding="wsHttpBinding" bindingConfiguration="wsHttpEndpointBinding"
        contract="AntragServiceRef.IAntragService" name="WSHttpBinding_IAntragService" behaviorConfiguration="SecuredBehaviour">
        <identity>
          <dns value="CertAzusClientTeststage"/>
        </identity>
      </endpoint>
      <endpoint address="http://server-xyz/Service/ImportService.svc"
        binding="wsHttpBinding" bindingConfiguration="wsHttpEndpointBinding"
        contract="ImportServiceRef.IImportService" name="WSHttpBinding_IImportService" behaviorConfiguration="SecuredBehaviour">
        <identity>
          <dns value="CertAzusClientTeststage"/>
        </identity>
      </endpoint>
      <endpoint address="http://server-xyz/Service/ReportService.svc"
        binding="wsHttpBinding" bindingConfiguration="wsHttpEndpointBinding"
        contract="ReportServiceRef.IReportService" name="WSHttpBinding_IReportService" behaviorConfiguration="SecuredBehaviour">
        <identity>
          <dns value="CertAzusClientTeststage"/>
        </identity>
      </endpoint>
      <endpoint address="http://server-xyz/Service/SettingsService.svc"
        binding="wsHttpBinding" bindingConfiguration="wsHttpEndpointBinding"
        contract="SettingsServiceRef.ISettingsService" name="WSHttpBinding_ISettingsService" behaviorConfiguration="SecuredBehaviour">
        <identity>
          <dns value="CertAzusClientTeststage"/>
        </identity>
      </endpoint>   
    </client>
  </system.serviceModel>
</configuration>

服务 Web.config:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=..." requirePermission="false" />
  </configSections>
  <appSettings>
      ...
  </appSettings>
  <system.web>
    <compilation debug="true" targetFramework="4.5" />
    <httpRuntime targetFramework="4.5" maxRequestLength="2097151"/>
    <globalization culture="de-DE" uiCulture="de-DE" />
  </system.web>

  <system.serviceModel>
    <bindings>
      <basicHttpBinding>
        <binding           
            maxBufferPoolSize="2147483647" maxBufferSize="524288" maxReceivedMessageSize="2147483647">
          <readerQuotas
            maxArrayLength="2147483647"
            maxBytesPerRead="2147483647"
            maxDepth="2147483647"
            maxNameTableCharCount="2147483647"
            maxStringContentLength="2147483647" />                          
        </binding>
        <binding 
            maxBufferPoolSize="2147483647" maxBufferSize="524288" maxReceivedMessageSize="2147483647" 
            name="secureBinding">
          <security mode="Transport" />
          <readerQuotas
            maxArrayLength="2147483647"
            maxBytesPerRead="2147483647"
            maxDepth="2147483647"
            maxNameTableCharCount="2147483647"
            maxStringContentLength="2147483647" />                          
        </binding>

      </basicHttpBinding>
      <wsHttpBinding>
        <binding name="wsHttpEndpointLokal" sendTimeout="00:05:00" 
            maxBufferPoolSize="2147483647" maxBufferSize="524288" maxReceivedMessageSize="2147483647" >
          <readerQuotas
            maxArrayLength="2147483647"
            maxBytesPerRead="2147483647"
            maxDepth="2147483647"
            maxNameTableCharCount="2147483647"
            maxStringContentLength="2147483647" />                          
        </binding>

        <binding name="wsHttpEndpointBindingSecured" sendTimeout="00:05:00" 
            maxBufferPoolSize="2147483647" maxBufferSize="524288" maxReceivedMessageSize="2147483647" >
          <security mode="Message">
            <message clientCredentialType="Certificate"/>
          </security>
          <readerQuotas
            maxArrayLength="2147483647"
            maxBytesPerRead="2147483647"
            maxDepth="2147483647"
            maxNameTableCharCount="2147483647"
            maxStringContentLength="2147483647" />                          
        </binding>

        <binding name="secureBindingWs" closeTimeout="00:01:00" openTimeout="00:01:00"
          receiveTimeout="00:15:00" sendTimeout="00:15:00" 
          messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"
          maxBufferPoolSize="2147483647" maxBufferSize="524288" maxReceivedMessageSize="2147483647" >
          <readerQuotas
            maxArrayLength="2147483647"
            maxBytesPerRead="2147483647"
            maxDepth="2147483647"
            maxNameTableCharCount="2147483647"
            maxStringContentLength="2147483647" />                          
        </binding>

        <binding name="wsHttpEndpointBinding" sendTimeout="12:00:00" 
            maxBufferPoolSize="2147483647" maxBufferSize="524288" maxReceivedMessageSize="2147483647" >
          <security mode="Message">
              <message clientCredentialType="Certificate"/>
          </security>
          <readerQuotas
            maxArrayLength="2147483647"
            maxBytesPerRead="2147483647"
            maxDepth="2147483647"
            maxNameTableCharCount="2147483647"
            maxStringContentLength="2147483647" />                          
        </binding>

      </wsHttpBinding>
    </bindings>
    <services>
      <service behaviorConfiguration="SecuredServiceBehaviour" name="MyApp.Service.AntragService">
        <endpoint address="" binding="wsHttpBinding" bindingConfiguration="wsHttpEndpointBindingSecured" contract="MyApp.Common.Service.IAntragService"/>
      </service>
      <service behaviorConfiguration="SecuredServiceBehaviour" name="MyApp.Service.ImportService">
        <endpoint address="" binding="wsHttpBinding" bindingConfiguration="wsHttpEndpointBindingSecured" contract="MyApp.Common.Service.IImportService"/>
      </service>
      <service behaviorConfiguration="SecuredServiceBehaviour" name="MyApp.Service.ReportService">
        <endpoint address="" binding="wsHttpBinding" bindingConfiguration="wsHttpEndpointBindingSecured" contract="MyApp.Common.Service.IReportService"/>
      </service>
      <service behaviorConfiguration="SecuredServiceBehaviour" name="MyApp.Service.SettingsService">
        <endpoint address="" binding="wsHttpBinding" bindingConfiguration="wsHttpEndpointBindingSecured" contract="MyApp.Common.Service.ISettingsService"/>
      </service>    
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="SecuredServiceBehaviour">
          <serviceCredentials>
            <clientCertificate>
              <authentication certificateValidationMode="PeerOrChainTrust"/>
            </clientCertificate>
            <serviceCertificate findValue="CertAzusClientTeststage" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName"/>
          </serviceCredentials>
          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="false"/>
          <serviceDebug includeExceptionDetailInFaults="true"/>
          <dataContractSerializer maxItemsInObjectGraph="2147483647"/>
        </behavior>

        <behavior>
          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true" />
          <dataContractSerializer maxItemsInObjectGraph="2147483647"/>
        </behavior>
      </serviceBehaviors>
      <endpointBehaviors>
        <behavior name="SecuredBehaviour">
          <dataContractSerializer maxItemsInObjectGraph="2147483647" />
          <clientCredentials>
            <clientCertificate findValue="CertAzusClientTeststage" x509FindType="FindBySubjectName" storeLocation="LocalMachine" storeName="My"/>
            <serviceCertificate>
              <authentication certificateValidationMode="PeerOrChainTrust"/>
            </serviceCertificate>
          </clientCredentials>
        </behavior>
      </endpointBehaviors>    
    </behaviors>
    <protocolMapping>
      <add binding="basicHttpsBinding" scheme="https" />
      <add binding="wsHttpBinding" scheme="https" bindingConfiguration="secureBindingWs"/>
    </protocolMapping>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
    <client>
      <endpoint 
        address="http://127.0.0.1/SecondService/StammdatenSvc.svc" 
        binding="wsHttpBinding" 
        bindingConfiguration="wsHttpEndpointBinding"
        behaviorConfiguration="SecuredBehaviour"
        contract="KV.Nordrhein.STMSAT.DataContract.ISatStammdatenSvc" 
        name="SatStammdatenSvc">
        <identity>
          <dns value="CertAzusClientTeststage"/>
        </identity>
      </endpoint>
    </client>
  </system.serviceModel>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true" />
    <directoryBrowse enabled="true" />
    <security>
      <requestFiltering>
        <requestLimits maxAllowedContentLength="198743680" />
      </requestFiltering>
    </security>
  </system.webServer>
  <entityFramework>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
      <parameters>
        <parameter value="v11.0" />
      </parameters>
    </defaultConnectionFactory>
    <providers>
      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
    </providers>
  </entityFramework>
  <connectionStrings>
      ...
  </connectionStrings>
</configuration>

【问题讨论】:

  • 遗憾的是没有一个答案能解决问题,所以我不得不使用一种解决方法,看看我自己的答案。

标签: .net wcf wcf-binding quota


【解决方案1】:

消息级安全和流模式不允许同时使用

见:http://msdn.microsoft.com/en-us/library/ms733137.aspx

【讨论】:

  • 我不知道我在示例中使用了流模式,还是大型请求需要流模式?
  • @SebastianBaltes:您当前没有配置流媒体。这可以通过binding 配置中的TransferMode 属性来完成,您在发布的代码中没有使用该属性。 TransferMode 默认情况下甚至不支持 wsHttpBinding,这需要定义自定义绑定。所以不,塞巴斯蒂安,你不是不小心使用了它。
【解决方案2】:

http://www.codeproject.com/Articles/521725/Request-Entity-Too-Large

您是否尝试过本文中提到的 uploadReadAheadSize?

【讨论】:

  • 不,没试过uploadReadAheadSize。我会试试这个,可能需要一些时间。
【解决方案3】:

尽管您配置了所有字节数组大小,但消息仍然显示“最大数组长度配额 (16384)”,这表示回退到默认值

这反过来表明您的配置中的某处存在错误。这样您配置的任何内容都不会被应用,而是使用默认值。请仔细阅读您的Web.config

我不确定您的endpoint 配置。我相信只允许一个端点配置address=""。其他端点需要各自指定一个唯一地址。 (这里有一个 MSDN 示例:Multiple Endpoints

如果您想让它们都使用相同的地址,则需要使用listenUri 属性对其进行配置。 (此处为 MSDN 文章:Multiple Endpoints at a Single ListenUri

[更新]

看看Web.config中的这段代码,我想这里可能有拼写错误。

<protocolMapping>
  <add binding="basicHttpsBinding" scheme="https" />
  [...]
</protocolMapping>

矛盾的是,在bindings 配置中,您设置了basicHttpBinding 而不是basicHttpsBinding 的所有数组最大长度。 => 请注意此处与http / https 协议的“s”的区别。

<system.serviceModel>
  <bindings>
    <basicHttpBinding>
    [...]
    </basicHttpBinding>
  </bindings>
</system.serviceModel>

这可能是错误消息引用默认数组大小的原因。您在错误的绑定类型 basicHttpBinding 上指定了数组大小,但改为使用 basicHttpsBinding,它仍然具有所有默认值。

=> 尝试将您的 basicHttpBinding 配置改为 basicHttpsBinding

【讨论】:

  • 非常感谢!我会把这个给我的客户,可能需要一些时间
【解决方案4】:

问题在于证书签名。签名对服务方法结果的部分进行加密。它通过加密结果的每个原始部分来做到这一点 - 如果它是一个字符串列表,则每个字符串都被单独加密。如果它是像我这样的单个大字节数组,那么大字节数组作为一个整体被加密,并且加密器失败,因为它大于 16 KB。我目前的解决方法是将大字节数组拆分为一个小字节数组块列表(每个 1 KB),现在它可以工作了。

另一种解决方案可能是使用流模式,但正如 cevauess 所写,流和消息级别的安全性不允许同时使用,在我的情况下,消息级别的安全性是一个要求。

【讨论】:

    猜你喜欢
    • 2011-03-05
    • 2012-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多