Клиент WCF: первый вызов не удался, второй вызов успешно - PullRequest
0 голосов
/ 09 мая 2018

У меня есть веб-сервис REST, который вызывает внешний веб-сервис SOAP с помощью клиента WCF. Этот веб-сервис REST размещен в IIS в нашей тестовой среде.

При вызове веб-службы REST, которая затем вызывает внешнюю веб-службу (с использованием клиента WCF), после перезапуска веб-службы REST в IIS первый вызов клиента WCF создает исключение SecurityNegotiationException . Второй вызов веб-службы REST, а также косвенные и все последующие вызовы завершаются успешно.

Чтобы проиллюстрировать это, вот изображение: SecurityNegotiationException

Это исключение SecurityNegotiationException выглядит следующим образом:

System.ServiceModel.Security.SecurityNegotiationException: Не удалось установить безопасный канал для SSL / TLS с полномочиями «X». ---> System.Net.WebException: запрос был прерван: не удалось создать безопасный канал SSL / TLS.

Конечная точка и привязка выглядят следующим образом (генерируется путем добавления ссылки на службу, слегка изменена привязка customBinding):

<endpoint address="https://..." binding="customBinding" bindingConfiguration="MyBinding" contract="WS_..." name="MyEndpoint" />
...
<customBinding>
    <binding name="MyBinding">
      <textMessageEncoding messageVersion="Soap11" />
      <security authenticationMode="UserNameOverTransport" />
      <httpsTransport requireClientCertificate="true" />
    </binding>
</customBinding>

Код, который вызывает внешний веб-сервис:

MyEndpointClient client = new MyEndpointClient("MyEndpoint");
client.ClientCredentials.UserName.UserName = authInfo.Username;
client.ClientCredentials.UserName.Password = authInfo.Password;
client.ClientCredentials.ClientCertificate.Certificate = authInfo.Certificate;
var result = client.requestInformation(parameters); // This fails the first time after IIS restart.

authInfo.Certificate загружается следующим образом:

authInfo.Certificate = new X509Certificate2(certificateBytes, certificatePassword);

Дополнительная информация:

  • Вызов внешней службы с использованием клиента WCF в первый раз (и все последующие вызовы) работает нормально, когда я запускаю локальный веб-сервис REST.
  • Я добавил WSDL веб-службы SOAP в проект, добавив ссылку на службу.
  • Для этого веб-сервиса требуются имя пользователя и пароль в сочетании с сертификатом. Необходимо использовать WSE3.0 (расширения безопасности Windows), я не могу использовать WSE2.0.
  • Сертификат загружается правильно в каждом случае, я окружил создание X509Certificate2 с помощью try-catch, который перехватывает CryptographicException и отменяет дальнейшую обработку в REST-webservice (вызов веб-службы SOAP не выполняется). Я подтвердил, что сертификат, с которым я тестирую, действителен.
  • При добавлении внешнего WSDL веб-службы SOAP он генерирует пользовательскую привязку (поэтому не BasicHttpBinding или WsHttpBinding, которые я пробовал вручную).
  • Внешний веб-сервис SOAP поддерживает TLS 1.0, 1.1 и 1.2 (протестировано с использованием SSLLabs ).
  • Веб-служба работает с правами администратора в тестовой среде.
  • IIS в тестовой среде работает в версии 8.5.9600.16384 в Windows Server 2012 R2 Standard

Что я пробовал и не решил проблему:

  • Вызов веб-службы SOAP второй раз (и более, до 10 раз) после первого раза, в том же жизненном цикле REST-вызова (дублируется строка client.RequestInformation (параметры) )
  • Создание нового MyEndpointClient после первого неудачного вызова и выполнение вызова с новым клиентом.
  • Загрузка сертификата из хранилища сертификатов
  • Загрузка сертификата из файла согласно рекомендации от этого блога (см. Совет 5)
  • Использование WsHttpBinding или BasicHttpBinding
  • Использование различных authenticationMode в теге security> в customBinding.
  • Использование localClientSettings reconnectTransportOnFailure = "true" /> в теге безопасности>
  • Настройка System.Net.ServicePointManager.Expect100Continue = true;
  • Настройка System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls12; (также пробовал TLS 1.0 и 1.1, а также Tls10 | Tls11 | Tls12 сразу)
  • Настройка System.Net.ServicePointManager.ServerCertificateValidationCallback + = (a, b, c, d) => true; (не очень хорошая идея, но стоит попробовать)
  • Настройка client.ClientCredentials.UseIdentityConfiguration = false; (также с использованием конфигурации Web.config с использованием поведений)
  • Настройка client.ClientCredentials.SupportInteractive = false; (также с использованием конфигурации Web.config с использованием поведений)

Любые идеи для получения первого вызова веб-службы SOAP, работающей какстабильны ли следующие звонки?

1 Ответ

0 голосов
/ 12 июня 2018

По какой-то причине это произошло только на одном тестовом сервере, а не на других серверах. Журнал трассировки вызова внешнего веб-сервиса SOAP показал, что внутренняя функция AcquireCredentialsHandle завершилась ошибкой с кодом ошибки 0X8009030D.

После еще одного расследования я обнаружил несколько сертификатов (от внешнего веб-сервиса SOAP), которые были установлены на рассматриваемом сервере. Похоже, они конфликтуют с вызовом внешнего веб-сервиса SOAP. После удаления этих сертификатов первый вызов теперь успешен!

Обновление : я снова столкнулся с той же проблемой, но теперь на моей машине для разработки. Очистка сертификатов не помогла, и все запросы завершились неудачно с тем же SecurityNegotiationException . Чтобы это исправить, я добавил сквозной код для кодов состояния HTTP 100 и принудительно установил соединение с TLS 1.2:

ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

Обратите внимание, что я добавил этот код до Я инициализировал клиента WCF ( MyEndpointClient в сообщении с вопросом), чтобы убедиться, что клиент WCF использует эти параметры.

...