在 WCF 中操纵肥皂

本文关键字:肥皂 操纵 WCF | 更新日期: 2023-09-27 17:55:13

对于一个项目,我们将连接到荷兰的KVK Handelsregister DataService。我们已经设置了一个 WCF 客户端代理类,但是我们的 soap 信封仍然与他们请求的信封不同,任何想法都可以解决以下 3 个问题:

  1. 删除必须理解属性
  2. 正文在元素中没有命名空间 (ns:)
  3. 标头也没有对 OASIS 的引用

我们的信封:

<s:Envelope xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:s="http://www.w3.org/2003/05/soap-envelope">
  <s:Header>
    <a:Action s:mustUnderstand="1">http://es.kvk.nl/genereerProduct</a:Action>
    <a:MessageID>urn:uuid:173035b3-714d-46ef-96c2-1d46962ec897</a:MessageID>
    <ActivityId CorrelationId="3d2fb1c7-99db-4c88-9745-6cd187281fc6" xmlns="http://schemas.microsoft.com/2004/09/ServiceModel/Diagnostics">5f48b058-21d5-46c4-8a8b-02f60556ef0e</ActivityId>
    <a:ReplyTo>
      <a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
    </a:ReplyTo>
    <a:To s:mustUnderstand="1">http://es.kvk.nl/KVK-DataserviceCT/2012/10</a:To>
  </s:Header>
  <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <genereerProduct xmlns="http://schemas.kvk.nl/schemas/hrip/generiekproduct/2013/01">
      <productRequest>
        <klantreferentie>QW43BA12</klantreferentie>
        <productnaam>Inschrijving</productnaam>
        <productsleutel>
          <kvkNummer>01048900</kvkNummer>
        </productsleutel>
      </productRequest>
    </genereerProduct>
  </s:Body>
</s:Envelope>

信封应该是

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
xmlns:oas="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" 
xmlns:ns="http://schemas.kvk.nl/schemas/hrip/generiekproduct/2013/01" 
xmlns:add="http://www.w3.org/2005/08/addressing">
            <soapenv:Header>
                        <add:Action>http://es.kvk.nl/genereerProduct</add:Action>
                        <add:MessageID>uuid://94-b0e0-d4313c898af0</add:MessageID>
                        <add:To>http://es.kvk.nl/KVK-DataserviceCT/2012/10</add:To>
            </soapenv:Header>
            <soapenv:Body>
                        <ns:genereerProduct>
                                    <ns:productRequest>
                                                <ns:klantreferentie>QW43BA12</ns:klantreferentie>
                                                <ns:productnaam>Inschrijving</ns:productnaam>
                                                <ns:productsleutel>
                                                            <ns:kvkNummer>01048900</ns:kvkNummer>
                                                </ns:productsleutel>
                                    </ns:productRequest>
                        </ns:genereerProduct>
            </soapenv:Body>
</soapenv:Envelope>*

按照下面注释中的要求,wsHttpBinding 和 customBinding 的绑定配置。更改此设置对 soap 信封没有影响,自定义绑定的错误是:

错误 接收 HTTP 响应时出错 https://webservices 8.kvk.nl/。这可能是由于服务终结点绑定未使用 HTTP 协议。这也可能是由于 HTTP 请求上下文 被服务器中止(可能是由于服务关闭 下)。有关更多 de tails,请参阅服务器日志。

<bindings>
  <wsHttpBinding>
    <binding name="ProductServiceSoap11">
      <security mode="Transport">
        <message clientCredentialType="Certificate"/>
        <transport clientCredentialType="Certificate" />
      </security>
    </binding>
  </wsHttpBinding>
  <customBinding>
    <binding name="WsHttpSoap11" >
      <transactionFlow />
      <textMessageEncoding messageVersion="Soap11WSAddressing10"  />
      <httpsTransport requireClientCertificate="true"  />
    </binding>
  </customBinding>
</bindings>

在 WCF 中操纵肥皂

至少我找到了正确的配置并使此链接正常工作。毕竟,摆弄 SOAP 信封只是此连接整个解决方案的一部分。

但是我会添加一些信息,这对我的工作有很大帮助。

1)日志记录,将其添加到您的配置文件中以开始日志记录

<system.diagnostics>
<sources>
  <source name="System.ServiceModel" switchValue="Information,ActivityTracing"
    propagateActivity="true">
    <listeners>
      <add name="xml" />
    </listeners>
  </source>
  <source name="System.ServiceModel.MessageLogging">
    <listeners>
      <add name="xml" />
    </listeners>
  </source>
</sources>
<sharedListeners>
  <add initializeData="c:''TestKVKService'TestKVKService'bin'Debug'Log'Tracesmore.svclog" type="System.Diagnostics.XmlWriterTraceListener"
    name="xml" />
</sharedListeners>
<trace autoflush="true" />

2)并将其添加到您的服务模型标签中。确保启用所有消息,当然还有logMessagesAtTransportLevel,因为这样您将看到消息是如何通过网络发送的。

 <system.serviceModel>
<diagnostics>
  <messageLogging
       logEntireMessage="true"
       logMalformedMessages="true"
       logMessagesAtServiceLevel="true"
       logMessagesAtTransportLevel="true"
       maxMessagesToLog="3000"
       maxSizeOfMessageToLog="64000"/>
</diagnostics>

3)最终的配置文件看起来像这样

  • 相互证书:因为消息在发送前已签名,并在接收时签名,使用2个不同的凭据,但那是在端点出价中指定
  • 消息保护顺序:使 WCF 对消息进行加密和签名
  • defaultAlgorithmSuite:因为 .NET 使用此 Java 服务器以外的其他算法
  • allowSerializedSigningTokenOnReply:因为响应也已签名
  • requireClientCertificate:将客户端证书发送到服务器
  • ExInspector:需要操作信封中的 TO
  • 客户端通过:因为它正在与中间路由器通信

最后但不是租赁:这个服务器向我发回空操作,所以我不得不摆弄生成的代理类。

     <bindings>
  <customBinding>
    <binding name="WsHttpSoap11" >
      <transactionFlow />
      <textMessageEncoding messageVersion="Soap11WSAddressing10"  />
      <security authenticationMode="MutualCertificate" 
                messageSecurityVersion="WSSecurity10WSTrust13WSSecureConversation13WSSecurityPolicy12BasicSecurityProfile10"
                 messageProtectionOrder="EncryptBeforeSign"
                defaultAlgorithmSuite="TripleDesRsa15" 
                allowSerializedSigningTokenOnReply="true" >
      </security>
      <httpsTransport requireClientCertificate="true"   />
    </binding>
  </customBinding>
</bindings>
<client>
  <endpoint address="http://other-endpoint-then-servername" binding="customBinding"
          bindingConfiguration="WsHttpSoap11" contract="ProductService"
          name="ProductServiceSoap11" behaviorConfiguration="myServiceBehaviour">
    <identity>
      <dns value="serverdnsname" />
    </identity>
  </endpoint>
</client>
<extensions>
  <behaviorExtensions>
    <add name="ExInspector" type="TestService.ExClientBehaviorExtensionElement, TestService"/>
  </behaviorExtensions>
</extensions>
<behaviors>
  <endpointBehaviors>
    <behavior name="myServiceBehaviour">
      <clientCredentials>
        <clientCertificate findValue="clientcertificatename" storeLocation="CurrentUser" x509FindType="FindBySubjectName" storeName="My" />
        <serviceCertificate >
          <defaultCertificate storeLocation="CurrentUser" storeName="My" findValue="servercertificatename" x509FindType="FindBySubjectName"  />
        </serviceCertificate>
      </clientCredentials>
      <clientVia viaUri="https://serverdnsname" />
      <ExInspector />
    </behavior>
  </endpointBehaviors>
</behaviors>

如果对该主题有任何疑问,请随时与我联系。浏览这个博客,它对我帮助很大:http://webservices20.blogspot.be/2012/06/12-common-wcf-interop-confusions.html