考虑一个WCF服务,其目的是在传输层具有必需的客户端证书(在IIS中将“客户端证书”设置为“必需”)。同样,在消息层将进行用户名认证。
现在我已经看到了这个问题:
而且我可以一定程度地了解正在发生的事情,并意识到WCF本质上不允许两者兼而有之。我在代码中执行了与上面引用的链接中的发布者相同的步骤,并且发现了相同的结果...正在传递消息级的UserName凭据(在我的情况下为SOAP标头),但是通过了客户端证书(尽管端点实际上未处理在VS调试中查看请求客户端时附加的附件)。
现在是让我感到困惑的部分。我决定对它进行一些修改。我想知道为什么它可以完全按照我的意愿工作……它超过了IIS Client Cert的要求,UserName被传递给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);
更复杂的是,适用于此的WCF服务是BizTalk服务。
这就是我最终完成此操作的方式。
服务器配置:
<customBinding>
<binding name="CustomCDARequestEndpointBinding">
<textMessageEncoding messageVersion="Soap11" />
<security authenticationMode="UserNameOverTransport" />
<httpsTransport requireClientCertificate="true" />
</binding>
</customBinding>
客户端配置:
<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>
使它起作用的关键是<httpsTransport requireClientCertificate="true" />
元素和<security authenticationMode="UserNameOverTransport"
元素/属性。
这种配置使我可以完全通过配置文件向WCF(BizTalk)服务提交消息,而无需更改实际代码。如上所示,它仍然允许我通过WebRequest提交给它。
我必须赞扬这篇文章:
以及这个:
将非BizTalk WCF配置转换为BizTalk WCF-Custom端点
终于使我走上正轨。我一直对WCF中的Custom Bindings视而不见,因为我以为这太过分了,但是它们的确没什么疯狂的,只是提供比现成可用的更详细的配置的一种方法。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句