Настройка привязки клиента WCF для использования сертификата X509 в dotnet core 2.2 - PullRequest
2 голосов
/ 07 июня 2019

Я пытаюсь преобразовать старый клиент WCF в ядро ​​dotnet. Я успешно сгенерировал свои прокси из wsdl и пытался настроить их так, чтобы я мог успешно вызвать конечную точку. Судя по некоторым поискам, кажется, что в ядре dotnet мне нужно настроить мой клиент WCF из кода.

Вот раздел конфигурации WCF из web.config старого приложения:

<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 голосов
/ 14 июня 2019

В интересах всех, кому может не повезти с той же проблемой, центральная проблема оказалась в том, что сертификат X509 не отправлялся . (Конечная точка, к которой мы обращались, приняла либо сертификат, либо базовую аутентификацию, то есть 401.)

Причина, по которой сертификат не отправлялся, заключалась в том, что сетевой стек ядра dotnet более строг, чем .NET, и для него требуется, чтобы для Расширенное использование ключа было установлено значение ClientAuthentication (1.3.6.1.5.5.7.3.2) или вообще не иметь EKU (см. исходный код здесь ). У нас не было - это было установлено для проверки подлинности сервера. Таким образом, сертификат был тихо сброшен, несмотря на то, что он был успешно загружен.

В этом выпуске github содержатся дополнительные сведения.

0 голосов
/ 07 июня 2019

Ваши фрагменты кода кажутся хорошими. Мы можем сделать еще одну вещь. когда сервер аутентифицирует клиента с помощью сертификата, мы должны установить доверительные отношения друг с другом, перейдите по ссылке ниже.
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>

Мы могли бы создать клиентский прокси-класс с помощью справочного провайдера веб-службы WCF Micorosoft. (Добавить подключенные службы). Не стесняйтесь, дайте мне знать, если есть что-то, с чем я могу помочь.
Авраам

...