У меня есть веб-сервис REST, который вызывает внешний веб-сервис SOAP с помощью клиента WCF. Этот веб-сервис REST размещен в IIS в нашей тестовой среде.
При вызове веб-службы REST, которая затем вызывает внешнюю веб-службу (с использованием клиента WCF), после перезапуска веб-службы REST в IIS первый вызов клиента WCF создает исключение SecurityNegotiationException . Второй вызов веб-службы REST, а также косвенные и все последующие вызовы завершаются успешно.
Чтобы проиллюстрировать это, вот изображение:
Это исключение 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, работающей какстабильны ли следующие звонки?