何使WCF客户端签名SecurityTokenReference

何使WCF客户端签名SecurityTokenReference

本文介绍了如何使WCF客户端签名SecurityTokenReference:参考的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要创建一个调用bea Web服务的WCF客户端.

I need to create a WCF client who calls a bea webservice.

我不断从网络服务获得此响应:

I keep getting this response from the webservice:

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

因此,我将注意力转向客户端服务通信的签名部分.

So I turn my attention to the signature part of the client<->service communication:

来自Web服务的wsdl的一部分:

Part of the wsdl from the webservice:

<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我知道我必须签名:

From the wsdl i understand that I must sign:

  1. SystemHeaders(我真正的问题)
  2. 时间戳(就是这样)
  3. 身体(对它进行了加密并对其进行了加密)

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

I have working code (using microsoft.web.services3) who produce this soap:

<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不是一个选择.抱歉.

I have promised to make this work using WCF, so microsoft.web.services3 is not an option. Sorry.

我已经使用svcutil创建了代理.没汗我对代理所做的唯一更改是我已添加

I have created the proxy using svcutil. No sweat. Only change I have made to the proxy by hand is that I have appended

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

到System.ServiceModel.ServiceContractAttribute

to the System.ServiceModel.ServiceContractAttribute

我当前的代码产生了以下符号部分:

My current code produces this sign part:

<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中:

from my 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:

I configure the CustomBinding in code like this:

    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代码中发生了什么(我还没有写过),看来作者完全重写了安全标头.这似乎不是最好的解决方案(但也许是唯一的解决方案?)

I have tried to understand what happens in the microsoft.web.services3 code who works (I havent written it), and it seems like the author completely rewrites the securityheader. This doesnt seem like the best solution (but maybe the only?)

有人可以帮我吗?

推荐答案

最后弄清楚了:-)

使用了这篇文章:

如何制作WCF客户端符合特定的WS-Security-对UsernameToken和SecurityTokenReference进行签名

在我写上面的问题之前,已经阅读了好几次(因此标题是如此相似),并且真的看不出为什么它应该起作用.但是确实如此!

Have read it several times before i wrote the question above (hence the titles are so similar), and could really not see why it should work. But it does!

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

My custom binding now looks like this:

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);

这篇关于如何使WCF客户端签名SecurityTokenReference:参考的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-27 21:52