Faire un appel HTTP en utilisant HttpClient

J’ai utilisé HttpClient pour faire des appels WebApi en utilisant C #. Semble propre et rapide par rapport à WebClient . Cependant, je suis coincé en faisant des appels Https .

Comment puis-je faire du code ci-dessous pour faire des appels Https ?

 HttpClient httpClient = new HttpClient(); httpClient.BaseAddress = new Uri("https://foobar.com/"); httpClient.DefaultRequestHeaders.Accept.Clear(); httpClient.DefaultRequestHeaders.Accept.Add( new MediaTypeWithQualityHeaderValue("application/xml")); var task = httpClient.PostAsXmlAsync( "api/SaveData", request); 

EDIT 1: Le code ci-dessus fonctionne bien pour effectuer des appels http. Mais quand je change le schéma en https, cela ne fonctionne pas. Voici l’erreur obtenue:

La connexion sous-jacente a été fermée: Impossible d’établir une relation de confiance pour le canal sécurisé SSL / TLS.

EDIT 2: Changer le schéma en https est: première étape.

Comment puis-je fournir un certificate et une clé publique / privée avec une demande C #?

Si le serveur ne prend en charge que la version TLS supérieure telle que TLS 1.2, il échouera à moins que votre PC client ne soit configuré pour utiliser une version TLS supérieure par défaut. Pour surmonter ce problème, ajoutez ce qui suit dans votre code.

 System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls; 

Modifier votre code exemple, ce serait

 HttpClient httpClient = new HttpClient(); //specify to use TLS 1.2 as default connection System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls; httpClient.BaseAddress = new Uri("https://foobar.com/"); httpClient.DefaultRequestHeaders.Accept.Clear(); httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/xml")); var task = httpClient.PostAsXmlAsync("api/SaveData", request); 

Spécifiez simplement HTTPS dans l’URI.

 new Uri("https://foobar.com/"); 

Foobar.com devra avoir un certificate SSL de confiance ou vos appels échoueront avec une erreur non fiable.

EDIT Answer: ClientCertificates avec HttpClient

 WebRequestHandler handler = new WebRequestHandler(); X509Certificate2 certificatee = GetMyX509Certificate(); handler.ClientCertificates.Add(certificatee); HttpClient client = new HttpClient(handler); 

EDIT Answer2: Si le serveur auquel vous vous connectez a désactivé SSL, TLS 1.0 et 1.1 et que vous exécutez toujours .NET Framework 4.5 (ou inférieur), vous devez choisir

  1. Mettre à niveau vers .Net 4.6+ ( Prend en charge TLS 1.2 par défaut )
  2. Ajoutez les modifications du registre pour demander à 4.5 de se connecter via TLS1.2 (voir: salesforce writeup pour compat et les clés pour modifier ou retirer IISCrypto voir Ronald Ramos répondre aux commentaires )
  3. Ajouter le code de l’application pour configurer manuellement .NET pour se connecter via TLS1.2 (voir la réponse de Ronald Ramos)

Votre code doit être modifié de cette manière:

 httpClient.BaseAddress = new Uri("https://foobar.com/"); 

Vous devez juste utiliser le schéma https: URI. Il existe une page utile sur MSDN concernant les connexions HTTP sécurisées. Effectivement:

Utilisez le schéma https: URI

Le protocole HTTP définit deux schémas URI:

http: utilisé pour les connexions non cryptées.

https: Utilisé pour les connexions sécurisées devant être chiffrées. Cette option utilise également des certificates numériques et des autorités de certificateion pour vérifier que le serveur est bien celui qu’il prétend être.

De plus, considérez que les connexions HTTPS utilisent un certificate SSL. Assurez-vous que votre connexion sécurisée possède ce certificate, sinon les demandes échoueront.

MODIFIER:

Le code ci-dessus fonctionne bien pour effectuer des appels http. Mais quand je change le schéma en https, cela ne fonctionne pas, laissez-moi poster l’erreur.

Qu’est-ce que cela signifie ne fonctionne pas? Les demandes échouent? Une exception est levée? Clarifiez votre question.

Si les demandes échouent, le problème doit être le certificate SSL.

Pour résoudre le problème, vous pouvez utiliser la classe HttpWebRequest , puis sa propriété ClientCertificate . De plus, vous pouvez trouver ici un exemple utile sur la façon de faire une requête HTTPS à l’aide du certificate.

Un exemple est le suivant (comme indiqué dans la page MSDN liée précédemment):

 //You must change the path to point to your .cer file location. X509Certificate Cert = X509Certificate.CreateFromCertFile("C:\\mycert.cer"); // Handle any certificatee errors on the certificatee from the server. ServicePointManager.CertificatePolicy = new CertPolicy(); // You must change the URL to point to your Web server. HttpWebRequest Request = (HttpWebRequest)WebRequest.Create("https://YourServer/sample.asp"); Request.ClientCertificates.Add(Cert); Request.UserAgent = "Client Cert Sample"; Request.Method = "GET"; HttpWebResponse Response = (HttpWebResponse)Request.GetResponse(); 

J’ai eu le même problème lors de la connexion à GitHub, qui nécessite un agent utilisateur. Il suffit donc de fournir cela plutôt que de générer un certificate

 var client = new HttpClient(); client.BaseAddress = new Uri("https://api.github.com"); client.DefaultRequestHeaders.Add( "Authorization", "token 123456789307d8c1d138ddb0848ede028ed30567"); client.DefaultRequestHeaders.Accept.Add( new MediaTypeWithQualityHeaderValue("application/json")); client.DefaultRequestHeaders.Add( "User-Agent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36"); 

Lorsque je me connecte à https j’ai aussi cette erreur, j’ajoute cette ligne avant HttpClient httpClient = new HttpClient(); et se connecter avec succès:

 ServicePointManager.ServerCertificateValidationCallback = delegate { return true; }; 

Je le sais de This Answer et d’un autre Anwser similaire et le commentaire mentionne:

C’est un hack utile dans le développement, donc il est préférable de ne pas faire de déclaration #if DEBUG #endif pour rendre cela plus sûr et éviter que cela ne se produise en production.

De plus, je n’ai pas essayé la méthode dans Another Answer qui utilise un new X509Certificate() ou un new X509Certificate2() pour créer un certificate, mais je ne suis pas sûr que simplement créer par new() fonctionne ou non.

EDIT: Quelques références:

Créer un certificate de serveur auto-signé dans IIS 7

Importation et exportation de certificates SSL dans IIS 7

Convertir .pfx en .cer

Les meilleures pratiques d’utilisation de ServerCertificateValidationCallback

Je trouve que la valeur de Thumbprint est égale à x509certificatee.GetCertHashSsortingng() :

Récupérer l’empreinte d’un certificate

Juste spécifier HTTPS dans l’URI devrait faire l’affaire.

 httpClient.BaseAddress = new Uri("https://foobar.com/"); 

Si la requête fonctionne avec HTTP mais échoue avec HTTPS, il s’agit très certainement d’un problème de certificate . Assurez-vous que l’appelant approuve l’émetteur du certificate et que le certificate n’a pas expiré. Un moyen rapide et facile de vérifier que c’est d’essayer de faire la requête dans un navigateur.

Vous pouvez également vouloir vérifier sur le serveur (si c’est le votre et / ou si vous le pouvez) qu’il est configuré pour servir correctement les requêtes HTTPS.

Vous pouvez essayer d’utiliser le package Nuget ModernHttpClient: Après avoir téléchargé le package, vous pouvez l’implémenter comme suit:

  var handler = new ModernHttpClient.NativeMessageHandler() { UseProxy = true, }; ; handler.ClientCertificateOptions = ClientCertificateOption.Automatic; handler.PreAuthenticate = true; HttpClient client = new HttpClient(handler); 

Je recevais aussi l’erreur:

La connexion sous-jacente a été fermée: Impossible d’établir une relation de confiance pour le canal sécurisé SSL / TLS.

… avec une application de ciblage Android Xamarin Forms qui tente de demander des ressources à un fournisseur d’API nécessitant TLS 1.3.

La solution consistait à mettre à jour la configuration du projet pour échanger le client http “managé” (.NET) de Xamarin (qui ne prend pas en charge TLS 1.3 à partir de Xamarin Forms v2.5), et utiliser plutôt le client natif Android.

C’est un projet simple à basculer dans Visual Studio. Voir la capture d’écran ci-dessous.

  • Propriétés du projet
  • Options Android
  • Avancée
  • Élément de la liste
  • Remplacez “Implémentation HttpClient” par “Android”
  • Remplacez l’implémentation SSL / TLS par “Native TLS 1.2+”

entrer la description de l'image ici

Ajoutez les déclarations ci-dessous à votre classe:

 public const SslProtocols _Tls12 = (SslProtocols)0x00000C00; public const SecurityProtocolType Tls12 = (SecurityProtocolType)_Tls12; 

Après:

 var client = new HttpClient(); 

Et:

 ServicePointManager.SecurityProtocol = Tls12; System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 /*| SecurityProtocolType.Tls */| Tls12; 

Content? 🙂

Pour erreur:

La connexion sous-jacente a été fermée: Impossible d’établir une relation de confiance pour le canal sécurisé SSL / TLS.

Je pense que vous devez accepter le certificate sans condition avec le code suivant

 ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true; 

comme Oppositional a écrit dans sa réponse pour interroger le client .NET se connectant à l’API Web de SSL .