带有客户端证书的WCF和"已超出最大阵列长度配额(16384)"

时间:2014-11-13 13:17:00

标签: .net wcf wcf-binding quota

我在从客户端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的问题之后,我尝试了几件事来增加所有绑定中的所有缓冲区和max-arguments,但最后仍然会得到相同的错误。奇怪的是,在切换到客户端证书之前,设置工作正常。有什么建议?

客户端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>

4 个答案:

答案 0 :(得分:2)

不允许消息级别安全性和流式传输模式

请参阅:http://msdn.microsoft.com/en-us/library/ms733137.aspx

答案 1 :(得分:0)

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

您是否尝试过使用uploadReadAheadSize,如本文所示?

答案 2 :(得分:0)

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

这反过来表示配置中的某处出现错误。因此,无论您配置什么都不会应用,而是使用默认值。请仔细阅读Web.config

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

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

<强> [UPDATE]

Web.config中查看此代码,我认为这里可能存在拼写错误。

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

相反,在bindings配置中,您已设置basicHttpBinding而不是basicHttpsBinding的所有数组最大长度。 =&GT;请注意此处与http / https协议的“ s ”的差异。

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

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

=&GT;请尝试将basicHttpBinding配置更改为basicHttpsBinding

答案 3 :(得分:0)

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

另一种解决方案可能是使用流式传输模式,但正如cevauess所写,流媒体和消息级安全性不允许在一起,并且消息级安全性是我的要求。