在dotnet core 2.2中配置WCF客户端绑定以使用X509证书

时间:2019-06-07 07:05:49

标签: wcf .net-core wcf-binding wcf-security

我正在尝试将旧的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新手,目前正在拔头发。

2 个答案:

答案 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提供了更多详细信息。