WCF Web服务请求:在SecurityTokenReference中添加引用标记而不是KeyIdentifier标记

时间:2019-04-30 12:46:18

标签: .net web-services wcf

我需要使用.NET使用Java Web服务。请求必须签名,并且证书必须包含在请求中。

使用下面的“ GetClient”方法时,除一个字段外,该请求是正确的。 在SecurityTokenReference元素中,添加了“ KeyIdentifier”。 此SecurityTokenReference字段应在'SignedInfo'元素中包含对第三参考的'Reference'字段:

</o:Security>
  </s:Header>
    <o:BinarySecurityToken>...</o:BinarySecurityToken>
    <Signature>
      <SignedInfo>
        <CanonicalizationMethod></CanonicalizationMethod>
        <SignatureMethod></SignatureMethod>
        <Reference URI="#_1">...</Reference>
        <Reference URI="#uuid-001">...</Reference>
        <Reference URI="#uuid-002">...</Reference>
      </SignedInfo>
      <SignatureValue>...</SignatureValue>
      <KeyInfo>
        <o:SecurityTokenReference>
          <o:KeyIdentifier >...</o:KeyIdentifier>
        </o:SecurityTokenReference>
      </KeyInfo>
    </Signature>
  </o:Security>
</s:Header>

所以

    <o:SecurityTokenReference>
      <o:KeyIdentifier >...</o:KeyIdentifier>
    </o:SecurityTokenReference>

应该是

    <o:SecurityTokenReference>
        <o:Reference ValueType="..." URI="uuid-002" />
    </o:SecurityTokenReference>

但是我无法正常工作。

使用

 InitiatorTokenParameters InclusionMode = SecurityTokenInclusionMode.Once

添加了正确的“ Reference”标记,但是随后生成了一个双重“ BinarySecurityToken”标记,从而导致Web服务被拒绝。 有什么解决办法吗?

public wsClient GetClient()  
{  

        CustomBinding b = new CustomBinding();
        HttpsTransportBindingElement transport = new HttpsTransportBindingElement();

        AsymmetricSecurityBindingElement asec = (AsymmetricSecurityBindingElement)SecurityBindingElement.CreateMutualCertificateBindingElement
            (MessageSecurityVersion.WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10);
        asec.SetKeyDerivation(false);
        asec.AllowInsecureTransport = true;
        asec.DefaultAlgorithmSuite = SecurityAlgorithmSuite.Basic256;
        asec.IncludeTimestamp = true;
        asec.ProtectTokens = true;
        asec.SecurityHeaderLayout = SecurityHeaderLayout.Lax;
        asec.InitiatorTokenParameters = new X509SecurityTokenParameters
        {
            InclusionMode = SecurityTokenInclusionMode.Never, //.Once, ----> Once creates correct SecurityTokenReference, but double BinarySecurityToken
            ReferenceStyle = SecurityTokenReferenceStyle.Internal
        };

        asec.EndpointSupportingTokenParameters.Signed.Add(new X509SecurityTokenParameters());
        TextMessageEncodingBindingElement textMessageEncoding = new TextMessageEncodingBindingElement(MessageVersion.Soap11, Encoding.UTF8);

        b.Elements.Add(asec);
        b.Elements.Add(textMessageEncoding);
        b.Elements.Add(transport);

        string url = "https://service";

        var c = new wsClient(b, new EndpointAddress(new Uri(url), 
            new DnsEndpointIdentity(kgParams.DnsEndpointIdentity), new AddressHeaderCollection()));


        X509Certificate cert = GetCertificate();
        c.ClientCredentials.ClientCertificate.Certificate = new X509Certificate2(cert);
        c.ClientCredentials.ServiceCertificate.DefaultCertificate = c.ClientCredentials.ClientCertificate.Certificate;
        c.Endpoint.Contract.ProtectionLevel = System.Net.Security.ProtectionLevel.Sign;

        return c;
}

1 个答案:

答案 0 :(得分:0)

After struggling for days with this issue, and not a single remark or answer on SO despite a bounty of 250 points, I can only come to the conclusion that this is an incompatibility between Java and .NET WCF.

In the end I simply abondoned WCF in frustration, and recreated the whole ***** request from scratch. This means:

  • Creating an XmlDocument containing the needed data
  • Add the certificate as Base64 to the header
  • Manually timestamp the request
  • Manually add the correct KeyInfo tag
  • Manually add all references using appropriate GUIDs
  • Sign all the elements manually using SignedXml and the certificate
  • Manually post the request

The server accepted the request without any complaint.