Effettua la chiamata Https utilizzando HttpClient

Ho usato HttpClient per fare chiamate WebApi usando C #. Sembra semplice e veloce rispetto a WebClient . Tuttavia sono bloccato mentre faccio le chiamate Https .

Come posso fare sotto codice per effettuare chiamate 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: il codice sopra funziona bene per effettuare chiamate http. Ma quando cambio lo schema in https non funziona. Ecco l’errore ottenuto:

La connessione sottostante è stata chiusa: imansible stabilire una relazione di trust per il canale protetto SSL / TLS.

MODIFICA 2: la modifica dello schema in https è la prima fase.

Come posso fornire il certificato e la chiave pubblica / privata insieme alla richiesta C #.

Se il server supporta solo versioni TLS più alte come TLS 1.2, continuerà a fallire a meno che il PC client non sia configurato per utilizzare la versione TLS più alta per impostazione predefinita. Per superare questo problema aggiungi quanto segue nel tuo codice.

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

Modificando il tuo codice di esempio, lo sarebbe

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

Basta specificare HTTPS nell’URI.

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

Foobar.com dovrà avere un certificato SSL attendibile o le tue chiamate falliranno con un errore non affidabile.

MODIFICA Risposta: ClientCertificates with HttpClient

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

MODIFICA Risposta2: Se il server a cui ci si sta connettendo ha disabilitato SSL, TLS 1.0 e 1.1 e si sta ancora utilizzando .NET Framework 4.5 (o sotto) è necessario effettuare una scelta

  1. Aggiornamento a .Net 4.6+ ( Supporta TLS 1.2 per impostazione predefinita )
  2. Aggiungi modifiche al registro per indicare 4.5 per connettersi su TLS1.2 (Vedi: salesforce writeup per compat e keys per cambiare OPPURE checker per IISCrypto vedere Ronald Ramos answer comment )
  3. Aggiungi il codice dell’applicazione per configurare manualmente .NET per connettersi su TLS1.2 (vedi risposta di Ronald Ramos)

Il tuo codice dovrebbe essere modificato in questo modo:

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

Devi solo usare lo schema https: URI. C’è una pagina utile qui su MSDN sulle connessioni HTTP sicure. Infatti:

Utilizza lo schema https: URI

Il protocollo HTTP definisce due schemi URI:

http: usato per connessioni non criptate.

https: utilizzato per connessioni protette che devono essere crittografate. Questa opzione utilizza anche certificati digitali e autorità di certificazione per verificare che il server sia quello che dichiara di essere.

Inoltre, considera che le connessioni HTTPS utilizzano un certificato SSL. Assicurati che la tua connessione protetta abbia questo certificato altrimenti le richieste falliranno.

MODIFICARE:

Sopra il codice funziona bene per effettuare chiamate http. Ma quando cambio lo schema in https non funziona, fammi pubblicare l’errore.

Cosa significa non funziona? Le richieste falliscono? Viene generata un’eccezione? Chiarisci la tua domanda

Se le richieste non riescono, il problema dovrebbe essere il certificato SSL.

Per risolvere il problema, puoi utilizzare la class HttpWebRequest e quindi la sua proprietà ClientCertificate . Inoltre, puoi trovare qui un utile esempio su come fare una richiesta HTTPS usando il certificato.

Un esempio è il seguente (come mostrato nella pagina MSDN collegata prima):

 //You must change the path to point to your .cer file location. X509Certificate Cert = X509Certificate.CreateFromCertFile("C:\\mycert.cer"); // Handle any certificate errors on the certificate 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(); 

Ho avuto lo stesso problema durante la connessione a GitHub, che richiede un agente utente. Quindi è sufficiente fornire questo piuttosto che generare un certificato

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

Quando si connette a https ho ricevuto anche questo errore, aggiungo questa riga prima di HttpClient httpClient = new HttpClient(); e connettersi con successo:

 ServicePointManager.ServerCertificateValidationCallback = delegate { return true; }; 

Lo so da questa risposta e un altro Anwser simile e il commento menziona:

Questo è un trucco utile per lo sviluppo, quindi inserire una #if DEBUG #endif su di esso è il minimo che si dovrebbe fare per renderlo più sicuro e fermare questo finire in produzione

Inoltre, non ho provato il metodo in Another Answer che usa il new X509Certificate() o il new X509Certificate2() per fare un certificato, non sono sicuro che semplicemente creo da new() funzionerà o meno.

EDIT: alcuni riferimenti:

Creare un certificato server autofirmato in IIS 7

Importa ed esporta certificati SSL in IIS 7

Convertire .pfx in .cer

Best practice per l’utilizzo di ServerCertificateValidationCallback

Trovo il valore di Thumbprint è uguale a x509certificate.GetCertHashString() :

Recupera l’identificazione personale di un certificato

Basta specificare HTTPS nell’URI dovrebbe fare il trucco.

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

Se la richiesta funziona con HTTP ma fallisce con HTTPS, questo è sicuramente un problema di certificato . Assicurarsi che il chiamante si fidi dell’assistente del certificato e che il certificato non sia scaduto. Un modo semplice e veloce per verificare che è quello di provare a fare la query in un browser.

Potresti anche voler controllare sul server (se è tuo e / o se puoi) che è impostato per servire correttamente le richieste HTTPS.

Puoi provare a utilizzare il pacchetto Nuget ModernHttpClient : dopo aver scaricato il pacchetto, puoi implementarlo in questo modo:

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

Stavo anche ricevendo l’errore:

La connessione sottostante è stata chiusa: imansible stabilire una relazione di trust per il canale protetto SSL / TLS.

… con un’applicazione di ottimizzazione Android di Xamarin Forms che tenta di richiedere risorse da un provider API che richiede TLS 1.3.

La soluzione era aggiornare la configurazione del progetto per sostituire il client http “gestito” (.NET) di Xamarin (che non supporta TLS 1.3 a partire da Xamarin Forms v2.5) e utilizzare invece il client nativo di Android.

È un semplice progetto che si triggers in Visual Studio. Vedi la schermata qui sotto.

  • Proprietà del progetto
  • Opzioni Android
  • Avanzate
  • Elemento dell’elenco
  • Cambia “Implementazione HttpClient” in “Android”
  • Modificare l’implementazione SSL / TLS in “Native TLS 1.2+”

inserisci la descrizione dell'immagine qui

Aggiungi le seguenti dichiarazioni alla tua class:

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

Dopo:

 var client = new HttpClient(); 

E:

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

Contento? 🙂

Per errore:

La connessione sottostante è stata chiusa: imansible stabilire una relazione di trust per il canale protetto SSL / TLS.

Penso che sia necessario accettare il certificato incondizionatamente con il seguente codice

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

come scritto Oppositional nella sua risposta alla domanda client .NET che si connette a API Web ssl .