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

Jon*_*att 5 wcf wcf-binding wcf-security .net-core

我正在尝试将旧的 WCF 客户端转换为 dotnet core。我成功地从 wsdl 生成了代理,并一直在尝试配置它们,以便我可以成功调用端点。根据一些谷歌搜索,似乎在 dotnet core 下我需要从代码配置我的 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>
Run Code Online (Sandbox Code Playgroud)

以下是我在 dotnet core 中配置它的方法:

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;
}
Run Code Online (Sandbox Code Playgroud)

这是我用来调用端点的代码(dotnet core代理尚不支持同步调用):

SearchResponse searchResponse = Task.Run(() => GetCustomerClient().SearchAsync(message)).Result;
Run Code Online (Sandbox Code Playgroud)

但是,我收到以下错误:

HTTP 请求未经客户端身份验证方案“匿名”的授权。从服务器收到的身份验证标头是“Basic Realm=”XISOAPApps“”

任何人都可以看到我的方法有什么问题或者建议我可以用来调试这个的方法吗?我是一名 WCF 新手,此时我正在抓狂。

Jon*_*att 7

为了其他可能不幸遇到同样问题的人的利益,核心问题是 X509证书没有被发送。(我们访问的端点接受证书或基本身份验证,因此是 401。)

未发送证书的原因是因为 dotnet 核心网络堆栈比 .NET 更严格,并且要求证书将其增强型密钥用法设置为ClientAuthentication (1.3.6.1.5.5.7.3.2)或根本没有 EKU(请参阅此处的源代码) 。我们的不是 - 它被设置为服务器身份验证。所以尽管加载成功,证书还是被悄悄丢弃了。

这个 github 问题提供了更多详细信息。