.net 如何使用带有客户端证书的HTTPS传输对带有证书的WCF消息进行签名

.net 如何使用带有客户端证书的HTTPS传输对带有证书的WCF消息进行签名,.net,wcf,web-services,ssl,.net,Wcf,Web Services,Ssl,编辑: 我最终确定IClientMessageInspector似乎不反映消息签名,所以当我在请求中实际获得签名时,我并不知道它。现在我要问一个新的真正的问题 如何配置WCF客户端以同时显示SSL客户端证书和对SOAP头签名? var myBinding = new BasicHttpBinding(); myBinding.Security.Mode = BasicHttpSecurityMode.TransportWithMessageCredential; myBinding.Securi

编辑:

我最终确定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 });

请发布工作soap示例(例如,供应商提供的示例)。顺便说一句,有比使用自定义绑定更激烈的动作:)

编辑:要同时使用传输和消息安全性,您需要自定义绑定。谷歌为“wcf绑定转换器”自动做到这一点。在自定义绑定而不是http元素中,将其更改为https并使用属性RequireVersionCertificate。对不起,我在手机上

编辑:


这很难看,但却完成了任务。如果在调试器中查看每个自定义绑定的元素,您会发现即使它们的堆栈底部都有一个HttpsTransportBindingElement,TransportWithMessageCredential实例将RequireClientCertificate设置为false,并且与证书相关的两个其他私有Memeber设置为false。传输实例将这些成员设置为true。这显然是国际海事组织WCF中的错误

下面的代码从customTransportSecurityBinding中获取“good”HttpStranSportBinding元素,并替换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);

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

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


我不能发布。有没有相关的部分,你正在寻找?我只需要什么之间的标签。你可以清理你想要的任何值,我只想看到元素结构。我误解了你最初的问题,认为你想要的是巨大的WSDL。我已经要求了一个工作样品,在得到你的答复后我又问了一次。他们说他们可以在“任何地方”处理签名,所以当我将签名元素放在标题中时,他们回答说他们需要它放在标题中的标记中。当我添加这一点时,我从他们那里得到了一个错误的请求响应。你不应该自己做签名,你应该让wcf做(它总是把它放在正确的位置)。ws-security有一些复杂性,因此很难继续使用soapsample@Yaron_Naveh我发现,将传输安全模式设置为TransportWithMessageCredential将获得标头中的签名块,但我不再获得为SSL相互身份验证提供的客户端证书。
<bindings>
      <customBinding>
        <binding name="SignedMessageBinding">
          <security messageSecurityVersion="WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10" /> 
          <textMessageEncoding messageVersion="Soap11" />
          <httpsTransport requireClientCertificate="true"  />
        </binding>
      </customBinding>
</bindings>