繁体   English   中英

具有X.509证书和Java Web Service的WCF客户端

[英]WCF Client With X.509 Certificate and Java Web Service

我目前正在尝试开发与第三方网络服务进行交互的客户端。 第三方Web服务是用Java编写的,我们已经为他们提供了用于签名消息的CA X509证书。 第三方指定WS-Security 1.1( http://docs.oasis-open.org/wss/v1.1/wss-v1.1-spec-os-SOAPMessageSecurity.pdf )。

我们能够成功地通过SoapUI对消息进行签名,发送并获得响应,但是我很难获得在WCF(.NET 4.5)中可以使用的相同功能。 我查看了从WCF客户端发送的消息(通过SvcTraceViewer和消息日志),它的格式似乎与SoapUI中的格式略有不同。

发送消息时,出现以下异常:

There was no endpoint listening at https://<service addres> that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details.

内部异常是“ Unable to connect to the remote server ,内部异常是A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond XXX.XXX.XXX.XXX:443

由于端点已建立且可用,因此我认为绑定设置不完全正确。

我在此处检查了有关SO的问题,包括使用X.509证书从WCF服务到Java Web服务对SOAP消息进行签名 ,并阅读了Yaron Naveh的12种常见wcf互操作性混淆 ,这些混淆虽然有所帮助,但还没有完全解决。

绑定定义:

<customBinding>
  <binding name="myCustomBinding">
    <textMessageEncoding messageVersion="Soap11" />
    <security authenticationMode="MutualCertificate"
              defaultAlgorithmSuite="Basic128Sha256Rsa15"
              includeTimestamp="true"
              messageSecurityVersion="WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10"
              securityHeaderLayout="LaxTimestampLast" />
    <httpsTransport />
  </binding>
</customBinding>

创建代理工厂的方法:

private Task<ChannelFactory<T>> CreateChannelFactory<T>(string bindingConfig, string address)
{

    EndpointAddress endpoint = new EndpointAddress(new Uri(address), EndpointIdentity.CreateDnsIdentity(<identity name>));
    ChannelFactory<T> proxy = new ChannelFactory<T>(new CustomBinding(bindingConfig), endpoint);
    proxy.Credentials.ClientCertificate.SetCertificate(storeLocation, storeName, findByType, findByValue);
    proxy.Credentials.ServiceCertificate.SetDefaultCertificate(storeLocation, storeName, findByType, findByValue);

    return Task.FromResult<ChannelFactory<T>>(proxy);
}

第三方实际上有几个服务(本质上每个服务一个操作合同),因此我在客户端启动时使用async/await为每个服务生成ChannelFactory<T>对象,证书的值storeLocationstoreNamefindByTypefindByValue为全局存储在客户端中(如果有人想知道的话)。

发送消息时,我从相应的工厂创建一个通道。 然后我得到了错误。

这是通过SoapUI发送的消息的相关部分(有效):

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
                  xmlns:view="http://<service namespace>">
  <soapenv:Header>
    <wsse:Security soapenv:mustUnderstand="1" 
                   xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" 
                   xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
      <wsse:BinarySecurityToken EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary" 
                                ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" 
                                wsu:Id="X509-F4F47BCAA968D14D08143033737254925">(data)</wsse:BinarySecurityToken>
      <ds:Signature Id="SIG-F4F47BCAA968D14D08143033737254928" 
                    xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
        <ds:SignedInfo>
          <ds:CanonicalizationMethod  Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
            <ec:InclusiveNamespaces PrefixList="soapenv view" 
                                    xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#"/>
          </ds:CanonicalizationMethod>
          <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
          <ds:Reference URI="#TS-F4F47BCAA968D14D08143033737254624">
            <ds:Transforms>
              <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
                <ec:InclusiveNamespaces PrefixList="wsse soapenv view" 
                                      xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#"/>
              </ds:Transform>
            </ds:Transforms>
            <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
            <ds:DigestValue>hg5n7PfuAfYb/LEawatI4ZBK0wmy14+Y6DihGhgBMI4=</ds:DigestValue>
          </ds:Reference>
        </ds:SignedInfo>
        <ds:SignatureValue>(data)</ds:SignatureValue>
        <ds:KeyInfo Id="KI-F4F47BCAA968D14D08143033737254926">
          <wsse:SecurityTokenReference wsu:Id="STR-F4F47BCAA968D14D08143033737254927">
            <wsse:Reference URI="#X509-F4F47BCAA968D14D08143033737254925" 
                            ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3"/>
          </wsse:SecurityTokenReference>
        </ds:KeyInfo>
      </ds:Signature>
      <wsu:Timestamp wsu:Id="TS-F4F47BCAA968D14D08143033737254624">
        <wsu:Created>2015-04-29T19:56:12Z</wsu:Created>
        <wsu:Expires>2015-04-29T19:56:17Z</wsu:Expires>
      </wsu:Timestamp>
    </wsse:Security>
  </soapenv:Header>
  <soapenv:Body>  
  <!-- Not relevant.  Not signed -->
  </soapenv:Body>
</soapenv:Envelope>

这是WCF使用指定的绑定生成的消息:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"
            xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
  <s:Header>
    <VsDebuggerCausalityData xmlns="http://schemas.microsoft.com/vstudio/diagnostics/servicemodelsink">uIDPo8j1TaWVCpRLgEy0S8UuwAcBAAAAAkQP7Rrb00auQ0G7/7Q0C1x7YNOf+kFOt9ioJVgbfFYACQAA</VsDebuggerCausalityData>
    <o:Security s:mustUnderstand="1" 
                xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
      <o:BinarySecurityToken>
        <!-- Removed-->
      </o:BinarySecurityToken>
      <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
        <SignedInfo>
          <CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></CanonicalizationMethod>
          <SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"></SignatureMethod>
          <Reference URI="#_1">
            <Transforms>
              <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></Transform>
            </Transforms>
            <DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
            <DigestValue>8KAbTZRA1cC60emKdKIiIm3zvv1jPPfVaia3a9l1c3g=</DigestValue>
          </Reference>
          <Reference URI="#uuid-5cb02cb6-0ae6-486d-ad2b-f9f9107b4576-2">
            <Transforms>
              <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></Transform>
            </Transforms>
            <DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
            <DigestValue>zR0k1GizuQekuM9WcSzVGssZowuzj3Dza/WGYmMqjSo=</DigestValue>
          </Reference>
        </SignedInfo>
        <SignatureValue>(data)</SignatureValue>
        <KeyInfo>
          <o:SecurityTokenReference>
            <o:Reference ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" 
                         URI="#uuid-96e7c3a3-cbe9-409e-ad49-9dcc07ef4360-2"></o:Reference>
          </o:SecurityTokenReference>
        </KeyInfo>
      </Signature>
      <u:Timestamp u:Id="uuid-5cb02cb6-0ae6-486d-ad2b-f9f9107b4576-2">
        <u:Created>2015-04-30T18:00:28.886Z</u:Created>
        <u:Expires>2015-04-30T18:05:28.886Z</u:Expires>
      </u:Timestamp>
    </o:Security>
  </s:Header>
  <s:Body u:Id="_1" 
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  </s:Body>
</s:Envelope>

这是WCF版本与SoapUI版本相比的差异/缺失项:

  • <BinarySecurityToken>缺少EncodingTypeValueTypeId属性。
  • <Signature>缺少Id属性。
  • '规范化方法missing
  • <Reference>两个元素,而不是1。不确定URI属性是什么(在WCF版本中)。
  • <KeyInfo>缺少Id属性。
  • <SecurityTokenReference>缺少Id属性。

其他所有内容似乎都匹配(名称空间前缀及其分配位置除外)。 我更愿意通过自定义绑定来执行此操作,但是如果我需要处理传出的请求,我愿意实现IClientMessageInspector

今天早上我能够解决此问题。 这里有两个问题。

第一个似乎与我公司的VPN有关。 我昨天能够在办公室中发送和接收回复(与我使用VPN时发布问题的日期相反)。 昨晚再次在VPN上,我收到了“ There was no endpoint listening at https://<service addres> that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details. There was no endpoint listening at https://<service addres> that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details. 再次异常,所以我将客户端部署到我们的开发服务器之一,并能够再次成功通信。

一旦能够发送邮件,便发现了第二个问题。 我在跟踪消息日志中看到了响应,但是收到了一个新的异常:

Security processor was unable to find a security header in the message. This might be because the message is an unsecured fault or because there is a binding mismatch between the communicating parties. This can occur if the service is configured for security and the client is not using security.

该请求已被客户端签名,但响应未签名。 将自定义绑定上的enableUnsecuredResponse属性设置为true可解决此问题。

最终的自定义绑定配置如下所示:

<customBinding>
    <textMessageEncoding messageVersion="1.1" />
    <security authenticationMode="MutualCertificate"
              defaultAlgorithmSuite="Basic128Sha256Rsa15"
              enableUnsecuredResponse="true"
              includeTimestamp="true"
              messageSecurityVersion="WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10"
              securityHeaderLayout="LaxTimestampLast" />
    <httpsTransport /> 
</customBinding>

设置证书的代码没有任何变化,只是将名称传递到EndpointIdentity.CreateDnsIdentity配置的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM