如何在 WCF 客户端中提供用户名和客户端证书(为什么此示例有效)?

Ben*_*ius 1 c# ssl wcf soap

考虑一个 WCF 服务,其目的是让传输层需要客户端证书(客户端证书在 IIS 中设置为“必需”)。同样,消息层也会有用户名认证。

现在我已经看到这个问题了:

禁止 WCF 客户端证书和用户名凭据

我可以在某种程度上理解那里发生的事情,并意识到 WCF 本质上不允许两者兼而有之。我在代码中执行了与上面引用的链接中的海报相同的步骤,并发现了相同的结果...正在传递消息级用户名凭据(在我的例子中是在 SOAP 标头中),但是客户端证书(尽管是在 VS 调试中查看请求客户端时附加)实际上并未由端点处理。

现在是让我感到困惑的部分。我决定对它进行一些破解。我想知道为什么它的工作原理与我想要的完全一样......它通过了 IIS 客户端证书要求,用户名被传递到 WCF 服务并且一切正常。然而,WCF 不允许我仅使用 WCF 配置文件或代码(我可以找到)来完成此操作。为什么?

            // sets up a proxy client based on endpoint config
            // basically just here to get the URL.
            this.InitializeSubmitClient();

            // these get used to create the HttpWebRequest
            string url = this.submitClient.Endpoint.Address.ToString();
            string action = "SubmitCDA";

            // this deserializes an XML file which is the "shell" of SOAP document and inject username/password into SOAP Security node
            XmlDocument soapEnvelopeXml = XMLHelper.CreateSoapDocument(this.txtSubmitCdaXmlFile.Text, this.txtAdAccount.Text, this.txtPassword.Text);
            HttpWebRequest webRequest = XMLHelper.CreateWebRequest(url, action);

            // saves the SOAP XML into the webRequest stream.
            XMLHelper.InsertSoapEnvelopeIntoWebRequest(soapEnvelopeXml, webRequest);

            // attach the cert
            if (this.chkSendClientCert.Checked)
            {
                X509Certificate myCert = X509Certificate.CreateFromCertFile(@"C:\temp\CDX-IHAT_DevClientCert.cer");
                webRequest.ClientCertificates.Add(myCert);
            }
            else
            {
                webRequest.ClientCertificates.Clear();
            }

            // begin async call to web request.
            IAsyncResult asyncResult = webRequest.BeginGetResponse(null, null);
Run Code Online (Sandbox Code Playgroud)

更复杂的是,它所适用的 WCF 服务是 BizTalk 服务。

Ben*_*ius 5

这就是我最终的做法。

服务器配置:

  <customBinding>
    <binding name="CustomCDARequestEndpointBinding">                    
      <textMessageEncoding messageVersion="Soap11" />
      <security authenticationMode="UserNameOverTransport" />
      <httpsTransport requireClientCertificate="true" />
    </binding>
  </customBinding>
Run Code Online (Sandbox Code Playgroud)

客户端配置:

<system.ServiceModel>
  <bindings>
    <customBindings>
      <binding name="CustomBinding_ITwoWayAsync">
          <security defaultAlgorithmSuite="Default"
            authenticationMode="UserNameOverTransport"
            requireDerivedKeys="true"
            includeTimestamp="true"
            messageSecurityVersion="WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10"
          >
            <localClientSettings detectReplays="false" />
            <localServiceSettings detectReplays="false" />
          </security>
          <textMessageEncoding messageVersion="Soap11" />
          <httpsTransport requireClientCertificate="true" />
      </binding>
    </customBinding>
  </bindings>
  <behaviors>
    <endpointBehaviors>
      <behavior name="ohBehave">
        <clientCredentials useIdentityConfiguration="false">
        <clientCertificate findValue="6D0DBF387484B25A16D0E3E53DBB178A366DA954" storeLocation="CurrentUser"
          x509FindType="FindByThumbprint" />            
        </clientCredentials>          
      </behavior>
    </endpointBehaviors>
  </behaviors>
  <client>
     <endpoint address="https://myservice/CDASubmitService/CDASubmit.svc"
        binding="customBinding" bindingConfiguration="SubmitDev" behaviorConfiguration="ohBehave"
        contract="CDASubmitService.CDASubmit" name="SubmitDev" />
  </client>
</system.serviceModel>
Run Code Online (Sandbox Code Playgroud)

让它工作的关键是<httpsTransport requireClientCertificate="true" />元素和<security authenticationMode="UserNameOverTransport"元素/属性。

此配置允许我完全通过配置文件向 WCF (BizTalk) 服务提交消息,而无需更改实际代码。它仍然允许我通过 WebRequest 提交给它,如上所示。

我必须赞扬这篇文章:

禁止 WCF 客户端证书和用户名凭据

还有这个:

将非 BizTalk WCF 配置转换为 BizTalk WCF 自定义终结点

终于让我走上了正轨。我总是回避 WCF 中的自定义绑定,因为我认为它太过分了,但它们实际上并不是什么疯狂的事情,只是一种提供比开箱即用的更详细配置的方法。