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
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.
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 .