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

时间:2012-05-21 16:18:22

标签: .net wcf web-services ssl

编辑:

我终于确定IClientMessageInspector似乎没有反映消息签名,所以当我在我的请求中实际获得签名时,我不知道它。所以,现在我的新问题......

如何配置WCF客户端以显示SSL客户端证书并签署SOAP标头?

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

这将导致标题具有已签名的时间戳。但是,客户端证书不再显示,我没有通过SSL。如果我将第二行更改为:

myBinding.Security.Mode = BasicHttpSecurityMode.Transport;

然后我通过SSL,但我的SOAP标头不再有签名块。

有什么方法可以获得HttpWebRequest,以便我可以像这样手动附加SSL客户端证书吗?

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

原始问题

我正在开发一个WCF客户端,该客户端需要与使用Forum Sentry网络设备来保护访问权限的第三方提供的服务互操作。它们需要SSL与传输级别的客户端证书以及带有签名的o:Security元素,并使用标头中的证书。我能够通过标准绑定实现其中一个或另一个,但我似乎无法同时发生这两种情况。理想情况下,他们希望使用与SSL客户端证书不同的证书签名的消息,但他们说我们可以使用相同的证书进行SSL客户端身份验证并签署消息。

我愿意在这一点上做任何事情,包括在必要时使用CustomBinding。

我可以使用以下方法使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 });

3 个答案:

答案 0 :(得分:2)

请发布样本工作肥皂(例如供应商提供的肥皂)。顺便说一下,使用自定义绑定会有更激烈的动作:)

编辑:要同时使用传输和邮件安全性,您需要自定义绑定。谷歌为“wcf绑定转换器”自动执行此操作。在自定义绑定而不是http元素中将其更改为https并使用属性requirevlientcertificate。对不起拼写我在手机上

编辑:

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

答案 1 :(得分:0)

这很难看但是完成了工作。如果你在调试器中查看每个自定义绑定的元素,你会看到即使它们的堆栈底部都有一个HttpsTransportBindingElement,TransportWithMessageCredential实例也会将RequireClientCertificate设置为false以及其他几个私有的部分与证书设置为false有关。 Transport实例将这些成员设置为true。这显然是WCF,IMO的错误。

下面的代码从customTransportSecurityBinding获取“good”HttpsTransportBindingElement,并替换customMessageCredentialBinding中的“bad”。然后,将修改后的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);

答案 2 :(得分:0)

如果有人为上述答案寻找app.config版本的自定义绑定:

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