2

我需要创建一个调用 bea webservice 的 WCF 客户端。

我不断从网络服务收到此响应:

无法使用任何受支持的令牌类型验证签名

所以我把注意力转向了客户端<->服务通信的签名部分:

来自网络服务的部分 wsdl:

<s0:Policy s1:Id="Sign.xml">
<wssp:Integrity xmlns:wls="http://www.bea.com/wls90/security/policy/wsee#part"
                xmlns:wssp="http://www.bea.com/wls90/security/policy"
                xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
  <wssp:SignatureAlgorithm URI="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
  <wssp:CanonicalizationAlgorithm URI="http://www.w3.org/2001/10/xml-exc-c14n#"/>
  <wssp:Target>
    <wssp:DigestAlgorithm URI="http://www.w3.org/2000/09/xmldsig#sha1"/>
    <wssp:MessageParts Dialect="http://www.bea.com/wls90/security/policy/wsee#part"> 
    wls:SystemHeaders()
  </wssp:MessageParts>
  </wssp:Target>
  <wssp:Target>
    <wssp:DigestAlgorithm URI="http://www.w3.org/2000/09/xmldsig#sha1"/>
    <wssp:MessageParts Dialect="http://www.bea.com/wls90/security/policy/wsee#part"> 
    wls:SecurityHeader(wsu:Timestamp)
  </wssp:MessageParts>
  </wssp:Target>
  <wssp:Target>
    <wssp:DigestAlgorithm URI="http://www.w3.org/2000/09/xmldsig#sha1"/>
    <wssp:MessageParts Dialect="http://schemas.xmlsoap.org/2002/12/wsse#part">
  wsp:Body()
  </wssp:MessageParts>
  </wssp:Target>
  <wssp:SupportedTokens>
    <wssp:SecurityToken 
      IncludeInMessage="true" 
      TokenType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3">
      <wssp:TokenIssuer>REMOVED</wssp:TokenIssuer>
    </wssp:SecurityToken>
  </wssp:SupportedTokens>
</wssp:Integrity>
<wssp:MessageAge Age="60" xmlns:wssp="http://www.bea.com/wls90/security/policy"/>

从 wsdl 我了解到我必须签名:

  1. SystemHeaders(我真正的问题)
  2. 时间戳(做了那个)
  3. 正文(做到了,并且还对其进行了加密)

我有生产这种肥皂的工作代码(使用 microsoft.web.services3):

<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
    <SignedInfo>
      <ds:CanonicalizationMethod 
        Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"
        xmlns:ds="http://www.w3.org/2000/09/xmldsig#" />
      <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
      <Reference URI="#Timestamp-fc23bf88-381b-4f2b-b992-ff07b41b5c38"> <!--This is the timestamp-->
        <Transforms>
          <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
        </Transforms>
        <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
        <DigestValue>Removed</DigestValue>
      </Reference>
      <Reference URI="#Id-4b4f1377-eac0-4db0-b334-384d7b14e286"> <!--This is the encrypted body-->
        <Transforms>
          <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
        </Transforms>
        <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
        <DigestValue>Removed</DigestValue>
      </Reference>
      <Reference URI="#SecurityToken-dcb8a392-5907-4432-80c6-cbe8f29a6117"> <!--This is the SecurityTokenReference:Reference-->
        <Transforms>
          <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
        </Transforms>
        <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
        <DigestValue>Removed</DigestValue>
      </Reference>
    </SignedInfo>
    <SignatureValue>Removed</SignatureValue>
    <KeyInfo>
      <wsse:SecurityTokenReference>
        <wsse:Reference 
          URI="#SecurityToken-dcb8a392-5907-4432-80c6-cbe8f29a6117" 
          ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" />
      </wsse:SecurityTokenReference>
    </KeyInfo>
  </Signature>
</wsse:Security>
</soap:Header>
<soap:Body wsu:Id="Id-4b4f1377-eac0-4db0-b334-384d7b14e286">
<xenc:EncryptedData 
 Id="Enc-8b5b4ef4-1c12-409b-8159-dec2889a8fa8" 
 Type="http://www.w3.org/2001/04/xmlenc#Content" 
 xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
  <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc" />
  <xenc:CipherData>
    <xenc:CipherValue>Removed<xenc:CipherValue>
  </xenc:CipherData>
</xenc:EncryptedData>
</soap:Body>

我已承诺使用 WCF 完成这项工作,因此 microsoft.web.services3 不是一个选项。对不起。

我已经使用 svcutil 创建了代理。没有汗水。我手动对代理所做的唯一更改是我已附加

, ProtectionLevel = System.Net.Security.ProtectionLevel.EncryptAndSign

到 System.ServiceModel.ServiceContractAttribute

我当前的代码产生这个标志部分:

<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="#_1"> <!--This is the body-->
        <Transforms>
          <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
        </Transforms>
        <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
        <DigestValue>Removed</DigestValue>
      </Reference>
      <Reference URI="#uuid-e7f22d2b-5a91-421a-aced-df7ab8a92f8d-1"> <!--This is the timestamp-->
        <Transforms>
          <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
        </Transforms>
        <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
        <DigestValue>Removed</DigestValue>
      </Reference>
    </SignedInfo>
    <SignatureValue>Removed</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-3b0e28b3-d47f-4eb2-ab0a-77f94dd76af0-2"/>
      </o:SecurityTokenReference>
    </KeyInfo>
  </Signature>
</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">
 <e:EncryptedData 
  Id="_2" 
  Type="http://www.w3.org/2001/04/xmlenc#Content" 
  xmlns:e="http://www.w3.org/2001/04/xmlenc#">
  <e:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc"/>
  <e:CipherData><e:CipherValue>Removed</e:CipherValue></e:CipherData>
</e:EncryptedData>
</s:Body>
</s:Envelope>

从我的 app.config:

  <system.serviceModel>
    <bindings>
      <customBinding>
        <binding name="testBinding">
          <textMessageEncoding maxReadPoolSize="64" maxWritePoolSize="16" 
                               messageVersion="Soap11" writeEncoding="utf-8">
            <readerQuotas maxDepth="32" maxStringContentLength="8192" 
                          maxArrayLength="16384" maxBytesPerRead="4096" 
                          maxNameTableCharCount="16384"/>
          </textMessageEncoding>
          <httpTransport manualAddressing="false" maxBufferPoolSize="524288" 
                         maxReceivedMessageSize="65536" allowCookies="false" 
                         authenticationScheme="Anonymous" bypassProxyOnLocal="false" 
                         hostNameComparisonMode="StrongWildcard" keepAliveEnabled="true" 
                         maxBufferSize="65536" proxyAuthenticationScheme="Anonymous" 
                         realm="" transferMode="Buffered" 
                         unsafeConnectionNtlmAuthentication="false" useDefaultWebProxy="true"/>
        </binding>
      </customBinding>
    </bindings>
    <client>
      <endpoint address="http://url.com/testservice/testservicePort" binding="customBinding" 
                bindingConfiguration="testBinding" 
                contract="testservicePortType" 
                name="testservicePort"/>
    </client>
  </system.serviceModel>

我在这样的代码中配置 CustomBinding:

    private static CustomBinding CreateCustomBinding()
    {
        var customBinding = new CustomBinding();

        SecurityBindingElement securityBindingElement = SecurityBindingElement.CreateMutualCertificateBindingElement(
                MessageSecurityVersion.WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10);

        AsymmetricSecurityBindingElement asymmetricSecurityBindingElement =
            (AsymmetricSecurityBindingElement)securityBindingElement;

        asymmetricSecurityBindingElement.SetKeyDerivation(false);

        asymmetricSecurityBindingElement.EnableUnsecuredResponse = true;

        asymmetricSecurityBindingElement.AllowInsecureTransport = true;
        asymmetricSecurityBindingElement.AllowSerializedSigningTokenOnReply = true;

        asymmetricSecurityBindingElement.DefaultAlgorithmSuite = SecurityAlgorithmSuite.TripleDesRsa15;

        asymmetricSecurityBindingElement.IncludeTimestamp = true;
        asymmetricSecurityBindingElement.MessageProtectionOrder = MessageProtectionOrder.SignBeforeEncrypt;
        asymmetricSecurityBindingElement.RequireSignatureConfirmation = false;

        asymmetricSecurityBindingElement.SecurityHeaderLayout = SecurityHeaderLayout.LaxTimestampFirst;

        customBinding.Elements.Clear();

        customBinding.Elements.Add(asymmetricSecurityBindingElement);

        customBinding.Elements.Add(new TextMessageEncodingBindingElement()
        {
            MessageVersion = MessageVersion.CreateVersion(EnvelopeVersion.Soap11,
            AddressingVersion.None),
            WriteEncoding = new System.Text.UTF8Encoding()
        });

        HttpTransportBindingElement httpbinding = new HttpTransportBindingElement();
        httpbinding.AuthenticationScheme = AuthenticationSchemes.Anonymous;
        httpbinding.MaxReceivedMessageSize = 1024 * 1024;
        customBinding.Elements.Add(httpbinding);
        return customBinding;
    }

我试图了解 microsoft.web.services3 代码中发生了什么(我还没有写过),似乎作者完全重写了 securityheader。这似乎不是最好的解决方案(但也许是唯一的?)

有人可以帮我吗?

4

1 回答 1

1

终于想通了:-)

用过这个帖子:

如何使 WCF 客户端符合特定的 WS-Security - 签署 UsernameToken 和 SecurityTokenReference

在我写上面的问题之前已经阅读了好几遍(因此标题非常相似),并且真的不明白为什么它应该起作用。但确实如此!

我的自定义绑定现在看起来像这样:

System.ServiceModel.Channels.AsymmetricSecurityBindingElement 
  asymmetricSecurityBindingElement = new AsymmetricSecurityBindingElement();
asymmetricSecurityBindingElement.MessageSecurityVersion = 
          MessageSecurityVersion.WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10;

asymmetricSecurityBindingElement.InitiatorTokenParameters = new
  System.ServiceModel.Security.Tokens.X509SecurityTokenParameters 
    { InclusionMode = SecurityTokenInclusionMode.Never };
asymmetricSecurityBindingElement.RecipientTokenParameters = new
  System.ServiceModel.Security.Tokens.X509SecurityTokenParameters
    { InclusionMode = SecurityTokenInclusionMode.Never };
asymmetricSecurityBindingElement.MessageProtectionOrder =
  System.ServiceModel.Security.MessageProtectionOrder.SignBeforeEncrypt;

asymmetricSecurityBindingElement.SecurityHeaderLayout = SecurityHeaderLayout.LaxTimestampFirst;
asymmetricSecurityBindingElement.EnableUnsecuredResponse = true;
asymmetricSecurityBindingElement.IncludeTimestamp = true;

asymmetricSecurityBindingElement.SetKeyDerivation(false);
asymmetricSecurityBindingElement.DefaultAlgorithmSuite = 
  System.ServiceModel.Security.SecurityAlgorithmSuite.TripleDesRsa15;

asymmetricSecurityBindingElement.EndpointSupportingTokenParameters.Signed.Add(
  new X509SecurityTokenParameters());

customBinding.Elements.Clear();
customBinding.Elements.Add(asymmetricSecurityBindingElement);
于 2012-11-20T12:50:52.437 回答