使用 WS 安全性在 WCF .NET 中向 Java Web 服务发送请求

Posted

技术标签:

【中文标题】使用 WS 安全性在 WCF .NET 中向 Java Web 服务发送请求【英文标题】:Sending requests to Java web service in WCF .NET with WS Security 【发布时间】:2021-11-13 00:07:46 【问题描述】:

我有一个需要与第 3 方 Java SOAP Web 服务通信的 .NET 应用程序。 Java 服务使用 WS 安全性。我有关于如何从 SoapUI 调用此 Web 服务的说明,并且能够成功发送请求。我很难尝试在 WCF 中实现此配置,以便向 Java Web 服务发送请求。

我已经能够在 SoapUI 中发送请求,它发送的内容如下:

<s:Header>
    <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
        <ds:Signature Id="SIG-252F850CD1BCBD83AA1631965258295205"
            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="s u"
                        xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#"/>
                </ds:CanonicalizationMethod>
                <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
                <ds:Reference URI="#id-252F850CD1BCBD83AA1631965258295204">
                    <ds:Transforms>
                        <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
                            <ec:InclusiveNamespaces PrefixList="u"
                                xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#"/>
                        </ds:Transform>
                    </ds:Transforms>
                    <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
                    <ds:DigestValue>digest value...</ds:DigestValue>
                </ds:Reference>
            </ds:SignedInfo>
            <ds:SignatureValue> signature... </ds:SignatureValue>
            <ds:KeyInfo Id="KI-252F850CD1BCBD83AA1631965258295202">
                <wsse:SecurityTokenReference u:Id="STR-252F850CD1BCBD83AA1631965258295203">
                    <ds:X509Data>
                        <ds:X509IssuerSerial>
                            <ds:X509IssuerName>CN=certname</ds:X509IssuerName>
                            <ds:X509SerialNumber>12345</ds:X509SerialNumber>
                        </ds:X509IssuerSerial>
                    </ds:X509Data>
                </wsse:SecurityTokenReference>
            </ds:KeyInfo>
        </ds:Signature>
    </wsse:Security>
</s:Header>

SoapUI 中的配置如下: 我使用 Web 服务 URL 在 SoapUI 中创建了一个项目。然后,我将密钥库添加到引用 .jks 文件的 Web 服务。然后,我使用密钥库添加签名类型的传出 WS-Security 配置。

SoapUI Outgoing Security Configuration

在 SoapUI 中的 Web 服务绑定上,在 Authorization 选项卡中,我选择 Basic Authorization 并将 Outgoing WSS 设置为该传出安全配置。

SoapUI Basic Authorization Configuration

完成后,我可以发送请求。

有谁知道如何在 WCF 中重现此配置?我已经开始了一些事情,但至少 KeyInfo 元素似乎缺少 X509IssuerSerial 数据。但是,我可能还缺少更多的部分。

这是我的 WCF 配置:

      <customBinding>
    <binding name="DigitalSignature">
      <textMessageEncoding messageVersion="Soap12" />
      <security defaultAlgorithmSuite="Basic128Rsa15" enableUnsecuredResponse="true"
                authenticationMode="MutualCertificate" includeTimestamp="false"
                messageSecurityVersion="WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10">
      </security>
      <httpTransport />
    </binding>
  </customBinding>

它为安全标头生成这个:

<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 u:Id="uuid-f59660cb-85d1-476a-9e3a-366c8c2d9d21-2" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">binary token...</o:BinarySecurityToken>
        <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
            <SignedInfo>
                <CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
                <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
                <Reference URI="#uuid-8c2cf70c-95bf-44f2-989c-a2b8d1385319-1">
                    <Transforms>
                        <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
                    </Transforms>
                    <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
                    <DigestValue>digest...</DigestValue>
                </Reference>
            </SignedInfo>
            <SignatureValue>signature...</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-f59660cb-85d1-476a-9e3a-366c8c2d9d21-2"/>
                </o:SecurityTokenReference>
            </KeyInfo>
        </Signature>
    </o:Security>
</s:Header>

【问题讨论】:

可以参考他的problems and solutions @Jiayao 谢谢你的建议。那个 SO 帖子不符合我正在寻找的确切安全协议。这是这些协议令人沮丧的部分原因......有很多,为一个非常具体的协议配置 WCF 非常困难。 【参考方案1】:

我知道我的问题非常具体。我注意到我的 WCF 配置生成的 XML 中的 SecurityTokenReference 元素的形状不正确。我做了一些搜索,似乎必须在代码中而不是在应用程序配置中配置 X509IssuerSerial。我可以通过创建一个自定义的 Binding 类来实现它。以下是最终为我工作的内容:

        public MyServiceBinding()
        
            var initiator = new X509SecurityTokenParameters(
                X509KeyIdentifierClauseType.IssuerSerial, SecurityTokenInclusionMode.Never);
            var recipient = new X509SecurityTokenParameters(
                X509KeyIdentifierClauseType.IssuerSerial, SecurityTokenInclusionMode.Never);
            var securityBinding = new AsymmetricSecurityBindingElement(initiator, recipient)
            
                IncludeTimestamp = false,
                SecurityHeaderLayout = SecurityHeaderLayout.Lax,
                MessageSecurityVersion = MessageSecurityVersion
                    .WSSecurity11WSTrust13WSSecureConversation13WSSecurityPolicy12,
                DefaultAlgorithmSuite = SecurityAlgorithmSuite.Basic128Rsa15,
                MessageProtectionOrder = MessageProtectionOrder.SignBeforeEncrypt,
                EnableUnsecuredResponse = true
            ;
            securityBinding.SetKeyDerivation(false);
            securityBinding.IncludeTimestamp = false;
            securityBinding.AllowInsecureTransport = true;
            securityBinding.LocalClientSettings.DetectReplays = false;
            Elements.Add(securityBinding);

            //Message Encoding
            var textMessageEncoding = new TextMessageEncodingBindingElement();
            textMessageEncoding.MessageVersion = MessageVersion.Soap12;
            textMessageEncoding.WriteEncoding = Encoding.UTF8;
            Elements.Add(textMessageEncoding);

            //Transport Binding
            var httpTransport = new HttpTransportBindingElement();
            Elements.Add(httpTransport);
        

也许有人会在某个时候在同一条船上发现这很有帮助。

【讨论】:

以上是关于使用 WS 安全性在 WCF .NET 中向 Java Web 服务发送请求的主要内容,如果未能解决你的问题,请参考以下文章

如何解决 .NET Core 客户端应用程序中的 WS2007HttpBinding WCF 服务绑定

SSL/TLS原理详解与WCF中的WS-Security

WCF 消息安全证书

WCF系列 - WCF安全系列 - basicHttpBinding

在 .NET Core 5 中使用 WCF (WSDL)

如何使用用户名/密码 + SSL 使用 WCF 配置安全 RESTful 服务