Отказ от HttpWebrequest с внутренним исключением. Аутентификация завершилась неудачно, поскольку удаленная сторона закрыла транспортный поток
Используя С#,.Net 4.5, я пытаюсь отправить веб-запрос через HttpWebRequest на удаленном сервере. См. Код ниже.
Я пробовал большинство решений, предлагаемых некоторыми форумами, но всегда получаю ту же ошибку. См. Ниже трассировку стека.
Ошибка вызывается при вызове метода request.GetReponse().
Дополнительная информация, в основном, я пытаюсь вызвать функцию reloadSslCertificate компонента vmware vCenter, установленного на удаленном сервере. В настоящее время ошибка происходит только в vCenter 5.5. Он отлично работает в версиях 5.1 и ниже.
var uri = String.Format("https://{0}/some_url", serverName);
var request = (HttpWebRequest)WebRequest.Create(uri);
request.KeepAlive = true;
request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
request.Headers.Set(HttpRequestHeader.AcceptLanguage, "en-US,en;q=0.8");
request.Credentials = credential;
request.CookieContainer = cookieContainer;
var response = request.GetResponse();
Исключение: System.Net.WebException: базовое соединение было закрыто: при отправке произошла непредвиденная ошибка. --- > System.IO.IOException: Ошибка аутентификации, поскольку удаленная сторона закрыл транспортный поток. в System.Net.Security.SslState.StartReadFrame(буфер Byte [], Int32 readBytes, AsyncProtocolRequest asyncRequest) в System.Net.Security.SslState.StartReceiveBlob(буфер Byte [], AsyncProtocolRequest asyncRequest) при System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken сообщение, AsyncProtocolRequest asyncRequest) в System.Net.Security.SslState.StartSendBlob(байт [] входящий, Int32 count, AsyncProtocolRequest asyncRequest) в System.Net.Security.SslState.ForceAuthentication(Boolean receiveFirst, Байт [], AsyncProtocolRequest asyncRequest) при System.Net.Security.SslState.ProcessAuthentication(LazyAsyncResult lazyResult) в System.Net.TlsStream.CallProcessAuthentication(объект государства) в System.Threading.ExecutionContext.RunInternal(ExecutionContext executeContext, обратный вызов ContextCallback, состояние объекта, логическое preserveSyncCtx) в System.Threading.ExecutionContext.Run(ExecutionContext executeContext, обратный вызов ContextCallback, состояние объекта, логическое preserveSyncCtx) в System.Threading.ExecutionContext.Run(ExecutionContext executeContext, обратный вызов ContextCallback, состояние объекта) в System.Net.TlsStream.ProcessAuthentication(результат LazyAsyncResult) в System.Net.TlsStream.Write(буфер байта [], смещение Int32, размер Int32) при System.Net.PooledStream.Write(буфер Byte [], смещение Int32, размер Int32) в System.Net.ConnectStream.WriteHeaders(Boolean async) --- Конец внутренняя трассировка стека исключений System.Net.HttpWebRequest.GetResponse()
Спасибо заранее.
Ответы
Ответ 1
Я просто хочу поделиться, что эта проблема уже решена.
Я только что изменил часть кода, где я установил протокол безопасности, прежде чем выпустить веб-запрос.
From:
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;
To:
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls;
Как оказалось, vCenter 5.5 использует TLS в качестве своего протокола SSL в своей конфигурации. Я надеюсь, что люди найдут это полезным, когда столкнутся с этой проблемой.
Ответ 2
Мы столкнулись с тем же исключением. В нашем случае ответ был невероятно похож на ответ @Dennis Laping. Другая команда настроила службу, которую мы пытались выполнить в Rancher балансировщик нагрузки, который по умолчанию не разрешал TLS 1.0 или SSL3. Как раз так, текущее значение по умолчанию для SecurityProtocol (без его установки) в .NET допускает только TLS 1.0 или SSL3.
Как только мы устанавливаем SecurityProtocol следующим образом, все работает нормально:
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
Все, что сказано, в документации для SecurityProtocol указано, что:
Ваш код никогда не должен зависеть от использования определенного уровня защиты или от предположения, что данный уровень безопасности используется по умолчанию. Если ваше приложение зависит от использования определенного уровня безопасности, вы должны явно указать этот уровень, а затем проверить, действительно ли он используется в установленном соединении. Кроме того, ваш код должен быть разработан таким образом, чтобы он был устойчивым перед лицом изменений, поддерживаемых протоколами, поскольку такие изменения часто делаются с небольшим предварительным уведомлением, чтобы смягчить возникающие угрозы.
Мы будем пересматривать то, что наилучшим образом подходит для нашей ситуации в протоколе, но пока я надеюсь, что это поможет кому-то другому.
Ответ 3
Посмотрите эту ссылку, это сработало для меня:
Как сделать HTTPS с TcpClient так же, как HttpWebRequest?
Dim trust_all_certificates As New CertificateOverride
ServicePointManager.ServerCertificateValidationCallback = AddressOf trust_all_certificates.RemoteCertificateValidationCallback
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3
Public Class CertificateOverride
Public Function RemoteCertificateValidationCallback(ByVal sender As Object, ByVal certificate As X509Certificate, ByVal chain As X509Chain, ByVal sslPolicyErrors As SslPolicyErrors) As Boolean
'CertEXPIRED = 2148204801
'CertVALIDITYPERIODNESTING = 2148204802
'CertPATHLENCONST = 2148204804
'CertROLE = 2148204803
'CertCRITICAL = 2148204805
'CertPURPOSE = 2148204806
'CertISSUERCHAINING = 2148204807
'CertMALFORMED = 2148204808
'CertUNTRUSTEDROOT = 2148204809
'CertCHAINING = 2148204810
'CertREVOKED = 2148204812
'CertUNTRUSTEDTESTROOT = 2148204813
'CertREVOCATION_FAILURE = 2148204814
'CertCN_NO_MATCH = 2148204815
'CertWRONG_USAGE = 2148204816
'CertUNTRUSTEDCA = 2148204818
Return True
End Function
End Class
P.S.
Я вставил эту строку кода перед тем, чтобы убедиться, что сертификат со стороны сервера принят: ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3