我正在尝试将旧的WCF客户端转换为dotnet核心。我从wsdl成功生成了代理,并一直在尝试配置它们,以便可以成功调用端点。基于某种搜索,看来我需要在dotnet核心下通过代码配置WCF客户端。
这是旧应用程序的web.config中的WCF配置部分:
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
<behaviors>
<endpointBehaviors>
<behavior name="clientEndpointCredential">
<clientCredentials>
<clientCertificate storeName="My" storeLocation="LocalMachine" x509FindType="FindBySubjectName" findValue="CERTNAME" />
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
<bindings>
<basicHttpBinding>
<binding name="OUR_Customer_OUTBinding" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" maxBufferSize="2147483647" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647" messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="5242880" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="Transport">
<transport clientCredentialType="Certificate" proxyCredentialType="None" realm="" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="https://the-full-url" behaviorConfiguration="clientEndpointCredential" binding="basicHttpBinding" bindingConfiguration="OUR_Customer_OUTBinding" contract="CustomerInterface.OUR_Customer_OUT" name="HTTPS_Port" />
</client>
<diagnostics>
<messageLogging logEntireMessage="true" logMalformedMessages="true" logMessagesAtServiceLevel="true" logMessagesAtTransportLevel="false" maxMessagesToLog="3000" />
</diagnostics>
</system.serviceModel>
这是我在dotnet核心中配置它的目的:
private OUR_Customer_OUTClient GetCustomerClient()
{
TimeSpan Minutes(int minutes) => new TimeSpan(0, minutes, 0);
var binding = new BasicHttpBinding();
binding.Name = "OUR_Customer_OUTBinding";
binding.AllowCookies = false;
binding.SendTimeout = Minutes(1);
binding.ReceiveTimeout = Minutes(10);
binding.OpenTimeout = Minutes(1);
binding.CloseTimeout = Minutes(1);
binding.MaxBufferPoolSize = 2147483647;
binding.MaxReceivedMessageSize = 2147483647;
binding.TextEncoding = Encoding.UTF8;
binding.TransferMode = TransferMode.Buffered;
binding.BypassProxyOnLocal = false;
binding.UseDefaultWebProxy = true;
binding.Security.Mode = BasicHttpSecurityMode.Transport;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
binding.Security.Transport.ProxyCredentialType = HttpProxyCredentialType.None;
var endpointAddress = new EndpointAddress("https://the-full-url");
var client = new OUR_Customer_OUTClient(binding, endpointAddress);
client.ClientCredentials.ClientCertificate.SetCertificate(
StoreLocation.LocalMachine,
StoreName.My,
X509FindType.FindBySubjectName,
"CERTNAME");
return client;
}
这是我用来调用端点的代码(dotnet核心代理尚不支持同步调用):
SearchResponse searchResponse = Task.Run(() => GetCustomerClient().SearchAsync(message)).Result;
但是,出现以下错误:
HTTP请求未经客户端身份验证方案“匿名”授权。从服务器收到的身份验证标头是“ Basic realm =“ XISOAPApps””
有人能看到我的方法有什么问题吗,或建议我可以用来调试此方法的方法吗?我是WCF新手,目前正在拔头发。
答案 0 :(得分:0)
您的代码段看起来不错。我们可能还有另一件事要做。当服务器使用证书对客户端进行身份验证时,我们应该建立相互之间的信任关系,请参考下面的链接。
https://docs.microsoft.com/en-us/dotnet/framework/wcf/feature-details/transport-security-with-certificate-authentication
此外,我们应该提供一个Identity标志来标识服务器,如下所示。
<client>
<endpoint address="http://vabqia593vm:4434/Service1.svc" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IService1" contract="ServiceReference1.IService1" name="WSHttpBinding_IService1" behaviorConfiguration="mybeh">
<identity>
<dns value="vabqia130vm"/>
</identity>
</endpoint>
</client>
我们可以通过Micorosoft WCF Web服务参考提供程序生成客户端代理类。(添加连接的服务)。
请随时告诉我是否有什么可以帮忙的。
亚伯拉罕
答案 1 :(得分:0)
为了使其他不幸的人无法解决同一问题,最主要的问题是 X509证书没有发送。 (我们要命中的端点接受了证书或基本身份验证,即401。)
之所以没有发送证书,是因为dotnet核心网络堆栈比.NET严格,并且要求证书的增强密钥用法设置为{{1 }}或完全没有EKU(请参阅source code here)。不是我们的-它设置为服务器身份验证。因此,尽管已成功加载证书,但它还是被悄悄丢弃了。
This github issue提供了更多详细信息。