web-dev-qa-db-fra.com

Échec sur HttpWebrequest avec exception interne L'authentification a échoué car la partie distante a fermé le flux de transport

En utilisant C #, .Net 4.5, j'essaie d'envoyer une demande Web via HttpWebRequest sur un serveur distant. Veuillez consulter le code ci-dessous. J'ai essayé la plupart des solutions proposées par certains forums mais je me retrouve toujours avec la même erreur. Veuillez voir la trace de la pile ci-dessous. L'erreur est levée lors de l'appel de la méthode request.GetReponse ().

Informations supplémentaires, essentiellement, j'essaie d'appeler la fonction reloadSslCertificate du composant vCenter de vmware installé sur un serveur distant. Actuellement, l'erreur ne se produit que sur vCenter 5.5. Cela fonctionne très bien dans les versions 5.1 et inférieures.

        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();

Exception: System.Net.WebException: la connexion sous-jacente a été fermée: une erreur inattendue s'est produite lors d'un envoi. ---> System.IO.IOException: l'authentification a échoué car la partie distante a fermé le flux de transport. à System.Net.Security.SslState.StartReadFrame (Byte [] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest) à System.Net.Security.SslState.StartReceiveBlob (Byte [] buffer, AsyncProtocolRequest asyncRequest) à System.Net.Sec. CheckCompletionBeforeNextReceive (message ProtocolToken, AsyncProtocolRequest asyncRequest) sur System.Net.Security.SslState.StartSendBlob (octet [] entrant, nombre Int32, AsyncProtocolRequest asyncRequest) sur System.Net.Security.SslState.ForceAstoolForceAssecForce, asyncRequest) sur System.Net.Security.SslState.ProcessAuthentication (LazyAsyncResult lazyResult) sur System.Net.TlsStream.CallProcessAuthentication (état d'objet) sur System.Threading.ExecutionContext.RunInternal (ExecutionContext executionContext, ContextCallback, Bext ObjectCallc System.Threading.ExecutionContext.Run (ExecutionContext executionContext, rappel ContextCallback, état d'objet, Boolean conserveSy ncCtx) sur System.Threading.ExecutionContext.Run (ExecutionContext executionContext, ContextCallback callback, Object state) sur System.Net.TlsStream.ProcessAuthentication (résultat LazyAsyncResult) sur System.Net.TlsStream.Write (octet [] tampon, décalage Int32, Int32 taille) à System.Net.PooledStream.Write (tampon octet [], décalage Int32, taille Int32) à System.Net.ConnectStream.WriteHeaders (async booléen) --- Fin de la trace de pile d'exceptions internes --- à System.Net .HttpWebRequest.GetResponse ()

Merci d'avance.

25
spitfyr86

Je veux juste partager que ce problème a déjà été résolu.

Je viens de modifier la partie du code où j'ai défini le protocole de sécurité avant d'émettre la demande Web.

De:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;

À:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls;

Il s'est avéré que vCenter 5.5 utilise TLS comme protocole SSL dans sa configuration. J'espère que les gens peuvent trouver cela utile lorsqu'ils rencontrent ce même problème.

26
spitfyr86

Nous avons rencontré la même exception. Dans notre cas, la réponse était incroyablement similaire à la réponse de @Dennis Laping. Une autre équipe avait configuré le service que nous essayions de lancer dans un équilibreur de charge Rancher , qui par défaut ne permettait pas TLS 1.0 ou SSL3. Il se trouve que la valeur par défaut actuelle pour SecurityProtocol (sans le définir) dans .NET n'autorise que TLS 1.0 ou SSL3.

Dès que nous avons défini SecurityProtocol comme suit, tout a bien fonctionné:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;

Cela étant dit, la documentation de SecurityProtocol indique que:

Votre code ne doit jamais dépendre implicitement de l'utilisation d'un niveau de protection particulier, ou de l'hypothèse qu'un niveau de sécurité donné est utilisé par défaut. Si votre application dépend de l'utilisation d'un niveau de sécurité particulier, vous devez spécifier explicitement ce niveau, puis vérifier qu'il est réellement utilisé sur la connexion établie. En outre, votre code doit être conçu pour être robuste face aux modifications des protocoles pris en charge, car ces modifications sont souvent apportées sans préavis afin d'atténuer les menaces émergentes.

Nous réévaluerons la meilleure solution à notre situation de protocole, mais pour l'instant j'espère que cela aide quelqu'un d'autre.

18
neumann1990

Voir ce lien, cela a fonctionné pour moi: Comment faire HTTPS avec TcpClient tout comme 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.

J'ai inséré cette ligne de code avant juste pour être sûr que le certificat côté serveur est accepté: ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3

1
MaGnumX