简体   繁体   English

如何使用带有客户端证书的HTTPS传输来签署带有证书的WCF消息

[英]How To Sign WCF Message With Certificate Using HTTPS Transport with Client Certificate

EDIT: 编辑:

I finally determined that IClientMessageInspector does not seem to reflect message signing so when I was actually getting a signature in my request I didn't know it. 我终于确定IClientMessageInspector似乎没有反映消息签名,因此当我在我的请求中实际获得签名时我不知道它。 So now for my new, real question... 所以现在我的新问题真正存在......

How can I configure a WCF client to present both the SSL client cert and sign the SOAP Header? 如何配置WCF客户端以呈现SSL客户端证书并签署SOAP头?

var myBinding = new BasicHttpBinding();
myBinding.Security.Mode = BasicHttpSecurityMode.TransportWithMessageCredential;
myBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
myBinding.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.Certificate;

This will result in the header having a timestamp that's signed. 这将导致标题具有已签名的时间戳。 However, the client cert is no longer presented and I don't get past SSL. 但是,客户端证书不再显示,我没有通过SSL。 If I change the second line to: 如果我将第二行更改为:

myBinding.Security.Mode = BasicHttpSecurityMode.Transport;

Then I get past SSL but my SOAP header no longer has the signing block. 然后我通过SSL但我的SOAP标头不再有签名块。

Is there any way I can get ahold of HttpWebRequest so that I can manually attach the SSL Client cert like so? 有什么方法可以让我得到HttpWebRequest,这样我就可以手动附加SSL客户端证书了吗?

webRequest.ClientCertificates.Add(certLoader.Load(@"c:\somecert.pfx"));

Original Question 原始问题

I am working on a WCF client that needs to interop with a service provided by a third party that's using a Forum Sentry network appliance to secure access. 我正在开发一个WCF客户端,它需要与使用Forum Sentry网络设备来保护访问权限的第三方提供的服务互操作。 They require SSL with a client cert at the transport level as well as an o:Security element with signature using an cert in the header. 它们需要SSL与传输级别的客户端证书以及带有签名的o:Security元素,并使用标头中的证书。 I'm able to achieve one or othe other with standard bindings, but I can't seem to get both to happen simultaneosly. 我能够通过标准绑定实现其中一个或另一个,但我似乎无法同时发生这两种情况。 Ideally, they want the message signed with a different cert from the SSL client cert but they said we could use the same cert for both the SSL client authentication and to sign the message. 理想情况下,他们希望使用与SSL客户端证书不同的证书签名的消息,但他们说我们可以使用相同的证书进行SSL客户端身份验证并签署消息。

I'm willing to do anything at this point to get this working including using a CustomBinding if necessary. 此时我愿意做任何事情以使其工作,包括在必要时使用CustomBinding。

I can get the SSL part working using the following: 我可以使用以下方法使SSL部分工作:

var myBinding = new BasicHttpBinding();
myBinding.Security.Mode = BasicHttpSecurityMode.Transport;
myBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
var url = "https://blah.com/services/somservice";
EndpointAddress ea = new EndpointAddress(url);
var client = new SoapClient(myBinding, ea);
var certLoader = new CertificateLoader("password");
client.ClientCredentials.ClientCertificate.Certificate = certLoader.Load(@"c:\somecert.pfx");
var resp = client.somemethod(ref profile, new RequestType { version = RequestTypeVersion.Item100 });

please publish a sample working soap (eg one the vendor provided). 请发布样本工作肥皂(例如供应商提供的肥皂)。 btw there are much more drastic moves than using a custom binding :) 顺便说一句,有比使用自定义绑定更激烈的动作:)

Edit: to use both transport and message security you need custom binding. 编辑:要使用传输和邮件安全性,您需要自定义绑定。 Google for "wcf binding converter" to do this automatically. 谷歌为“wcf绑定转换器”自动执行此操作。 In the custom binding instead of http element change it to https and use attribute requirevlientcertificate. 在自定义绑定而不是http元素中将其更改为https并使用属性requirevlientcertificate。 Sorry for spelling I'm on mobile 对不起拼写我在手机上

EDIT: 编辑:

var c = new CustomBinding();            
MessageSecurityVersion version = MessageSecurityVersion.WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10;
var sec = SecurityBindingElement.CreateCertificateOverTransportBindingElement(version);
c.Elements.Add(sec);
c.Element.Add(new TextMessageEncodingBindingElement() { MessageVersion = MessageVersion.Soap11 };)
c.Elements.Add(new HttpsTransportBindingElement() { RequireClientCertificate = true });

This is ugly but gets the job done. 这很丑陋,但完成了工作。 If you look at the elements of each of these custom bindings in the debugger, you'll see that even though both have an HttpsTransportBindingElement at the bottom of their stack, the TransportWithMessageCredential instance will have RequireClientCertificate set to false and a couple of other private memebers relating to the certificate set to false. 如果你在调试器中查看每个自定义绑定的元素,你会看到即使它们的堆栈底部都有一个HttpsTransportBindingElement,TransportWithMessageCredential实例也会将RequireClientCertificate设置为false以及其他几个私有成员。与证书设置为false有关。 The Transport instance will have these members set to true. Transport实例将这些成员设置为true。 This is clearly bug in WCF, IMO. 这显然是WCF,IMO的错误。

The code below takes the "good" HttpsTransportBindingElement from the customTransportSecurityBinding and replaces the "bad" one in the customMessageCredentialBinding. 下面的代码从customTransportSecurityBinding获取“good”HttpsTransportBindingElement,并替换customMessageCredentialBinding中的“bad”。 You then pass the modified customMessageCredentialBinding into your client constructor. 然后,将修改后的customMessageCredentialBinding传递给客户端构造函数。

    var transportSecurityBinding = new BasicHttpBinding();
    transportSecurityBinding.Security.Mode = BasicHttpSecurityMode.Transport;
    transportSecurityBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
    transportSecurityBinding.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.Certificate;
    var customTransportSecurityBinding = new CustomBinding(transportSecurityBinding);

    var messageCredentialBinding = new BasicHttpBinding();
    messageCredentialBinding.Security.Mode = BasicHttpSecurityMode.TransportWithMessageCredential;
    messageCredentialBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
    messageCredentialBinding.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.Certificate;
    var customMessageCredentialBinding = new CustomBinding(messageCredentialBinding);

    // replace transport binding element from message credential binding with the transportSecurityBinding transport binding
    // which will include the cert for SSL mutual auth.
    customTransportSecurityBinding.Elements[customTransportSecurityBinding.Elements.Count - 1] = customMessageCredentialBinding.Elements[customMessageCredentialBinding.Elements.Count - 1];

var client = new SomeSoapClient(customTransportSecurityBinding, ea);

In case if anyone looking for app.config version of custom binding for the above answer: 如果有人为上述答案寻找app.config版本的自定义绑定:

<bindings>
      <customBinding>
        <binding name="SignedMessageBinding">
          <security messageSecurityVersion="WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10" /> 
          <textMessageEncoding messageVersion="Soap11" />
          <httpsTransport requireClientCertificate="true"  />
        </binding>
      </customBinding>
</bindings>

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

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