HttpClient kullanarak Https çağrısı yapın


157

Kullanıyorum HttpClient C # kullanarak WebAPI görüşme yapmak için. İle karşılaştırıldığında düzgün ve hızlı bir şekilde görünüyor WebClient. Ancak Httpsarama yaparken takıldım .

HttpsArama yapmak için aşağıdaki kodu nasıl yapabilirim ?

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<DeviceRequest>(
                "api/SaveData", request);

DÜZENLEME 1: Yukarıdaki kod http çağrıları yapmak için iyi çalışıyor. Ancak şemayı https olarak değiştirdiğimde işe yaramaz. Elde edilen hata:

Temel bağlantı kapatıldı: SSL / TLS güvenli kanalı için güven ilişkisi kurulamadı.

DÜZENLEME 2: Şemanın https olarak değiştirilmesi birinci adım.

C # isteğiyle birlikte sertifika ve genel / özel anahtarı nasıl sağlayabilirim.


2
sadece belirterek https aramaları new Uri("https://foobar.com/");
yapıyorsunuz

2
Kafam karıştı. Bu zaten çalışmıyor mu? Hata mı alıyorsunuz? (Düzenleme: OP
Tim

Yanıtlar:


215

Sunucu yalnızca TLS 1.2 gibi daha yüksek TLS sürümünü destekliyorsa, istemci bilgisayarınız varsayılan olarak daha yüksek TLS sürümünü kullanacak şekilde yapılandırılmadığı sürece yine de başarısız olur. Bu sorunun üstesinden gelmek için kodunuza aşağıdakileri ekleyin.

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

Örnek kodunuzu değiştirmek,

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<DeviceRequest>("api/SaveData", request);

@DerekS Memnun oldunuz ve rica ederim. Herhangi bir nedenle, üretim ayarındaki kodu değiştiremez, ancak sunucuda bazı yönetici yapabiliyorsanız, bu yardımcı programı varsayılan olarak TLS 1.2 yapılandırmak için kullanın. nartac.com/Products/IISCrypto
Ronald Ramos

SecurityProtocolType.Tls12bahsettiğiniz bu enum değerlerini bulamadı
JobaDiniz

1
@JobaDiniz .NET 4.5 veya üstünü kullanır ve System.Net ad alanını içerir.
Ronald Ramos

SecurityProtocol ayarının yalnızca bir kez yapılması gerekiyor mu? Uygulama başlangıcında gibi mi?
CamHart

Harika çalışıyor. Teşekkürler. Ben de bu HttpClient istemcisi = yeni HttpClient () kullanılan herhangi bir üstbilgileri temizlemek gerek yoktu bulundu; ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls; HttpResponseMessage yanıtı = client.GetAsync ("https: // ...");
AtLeastTheresToast

127

URI'de HTTPS'yi belirtmeniz yeterlidir.

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

Foobar.com'un güvenilir bir SSL sertifikasına sahip olması gerekir veya aramalarınız güvenilmeyen bir hata ile başarısız olur.

EDIT Cevabı: HttpClient ile İstemci Sertifikaları

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

Cevap2 DÜZENLE: Bağlandığınız sunucu SSL, TLS 1.0 ve 1.1'i devre dışı bıraktıysa ve hala .NET framework 4.5 (veya aşağısı) çalıştırıyorsanız, bir seçim yapmanız gerekir

  1. Net 4.6+ sürümüne yükseltin ( Varsayılan olarak TLS 1.2'yi destekler )
  2. TLS1.2 üzerinden bağlanmaya 4.5 talimat defteri değişikliklerini ekleme (Bkz: satış gücü writeup COMPAT ve değişim VEYA çıkış anahtarlarını IISCrypto Ronald Ramos bkz cevap yorumlarınızı )
  3. .NET'i TLS1.2 üzerinden bağlanacak şekilde manuel olarak yapılandırmak için uygulama kodu ekleyin (bkz. Ronald Ramos yanıtı )

@felickz büyük tepki. Windows 8 için WebRequestHandler kütüphanesine eşdeğer bir şey var mı?
Billatron

@ WP / Win8 için Billatron farklı kütüphaneler .. bkz.
felickz

6
Kendinden imzalı sertifikalar geliştirirken veya bunlarla uğraşırken aşağıdakilerle güvenilmeyen sertifika hatalarını göz ardı edebilirsiniz: ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;
geliştirici

6
Nedir GetMyX509Certificate?
Fandi Susanto

6
@developer, kodun üretim üretiminize girmeyeceğini umuyoruz :)
felickz

15

Kodunuz şu şekilde değiştirilmelidir:

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

Sadece https:URI şemasını kullanmalısınız . MSDN'de güvenli HTTP bağlantıları hakkında yararlı bir sayfa var . Aslında:

Https: URI şemasını kullanın

HTTP Protokolü iki URI şeması tanımlar:

http: Şifresiz bağlantılar için kullanılır.

https: Şifrelenmesi gereken güvenli bağlantılar için kullanılır. Bu seçenek, sunucunun iddia ettiği kişi olduğunu doğrulamak için dijital sertifikalar ve sertifika yetkilileri de kullanır.

Ayrıca, HTTPS bağlantılarının SSL sertifikası kullandığını düşünün. Güvenli bağlantınızın bu sertifikaya sahip olduğundan emin olun, aksi takdirde istekler başarısız olur.

DÜZENLE:

Yukarıdaki kod http aramaları yapmak için iyi çalışıyor. Ama şemayı https olarak değiştirdiğimde işe yaramıyor, hatayı göndermeme izin verin.

Çalışmaması ne anlama geliyor? İstekler başarısız mı? Bir istisna atılıyor mu? Sorunuzu netleştirin.

İstekler başarısız olursa, sorunun SSL sertifikası olması gerekir.

Sorunu çözmek için önce sınıfı HttpWebRequest, sonra da özelliğini kullanabilirsiniz ClientCertificate. Ayrıca, bulabilirsiniz burada sertifika kullanarak bir HTTPS isteği yapmak konusunda yararlı bir örnek.

Bir örnek şöyledir (daha önce bağlanmış olan MSDN sayfasında gösterildiği gibi):

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

Öncelikle, hile istekle birlikte sertifika gönderme yatıyor. bu nasıl yapılır?
Abhijeet

"C: \\ mycert.cer" dosyasını nereden edinebilirsiniz? Mycert.cer dosyası nasıl oluşturulur?
masiboo

@masiboo Yazdıklarım HTTPS çağrılarının nasıl yapılacağını cevaplar. Google'a nasıl bir * .cer dosyası oluşturacağınızı sorun, yanıtı kendiniz bulacaksınız.
Alberto Solano

9

Bağlanınca httpsda bu hatayı aldım, bu satırı daha önce ekledim HttpClient httpClient = new HttpClient();ve başarıyla bağlandım:

ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };

Ben bu cevap ve başka bir benzer Anwser biliyorum ve yorum bahseder:

Bu, geliştirme konusunda yararlı bir hack'tir, bu yüzden #if DEBUG #endif ifadesini etrafına koymak, bunu daha güvenli hale getirmek ve üretimde sona erdirmeyi durdurmak için yapmanız gereken en az şeydir.

Ayrıca, başka bir cevap kullanan new X509Certificate()veya new X509Certificate2()bir sertifika yapmak için yöntem denemedim, sadece new()işe yarayacak ya da değil oluşturmak emin değilim .

EDIT: Bazı Referanslar:

IIS 7'de Kendinden İmzalı Sunucu Sertifikası Oluşturma

IIS 7'de SSL Sertifikalarını İçe ve Dışa Aktarma

.Pfx birimini .cer birimine dönüştür

ServerCertificateValidationCallback kullanmak için en iyi uygulamalar

Thumbprint'in değerine eşit olduğunu düşünüyorum x509certificate.GetCertHashString():

Sertifikanın Parmak İzini Alma


6

Bir kullanıcı aracısı gerektiren GitHub'a bağlanırken aynı sorunu yaşadım. Bu nedenle bir sertifika oluşturmak yerine bunu sağlamak yeterlidir

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

2
İnternet ile paylaştığınız belirteci iptal etmelisiniz, sanırım GitHub bunu otomatik olarak yapmış olabilir.
Amias

21
Gerçekten benim simgemin başlayacağını mı düşünüyorsun 123456789??
Carlo V.Dango

5

Şu düzeyde küresel olmayan bir ayar vardır HttpClientHandler:

var handler = new HttpClientHandler()
{
    SslProtocols = SslProtocols.Tls12 | SslProtocols.Tls11 | SslProtocols.Tls
};

var client = new HttpClient(handler);

Böylece en son TLS sürümleri kullanılabilir.

Varsayılan değerin SslProtocols.Defaultaslında olduğunu unutmayın. SslProtocols.Ssl3 | SslProtocols.Tls(.Net Core 2.1 ve .Net Framework 4.7.1 için kontrol edilir).


Cevap için teşekkürler. Küçük bir not: bu belgeye göre: docs.microsoft.com/en-us/dotnet/api/… En azından çerçeve 4.7.1 gerektirir.
GELR

@GELR evet, haklısın. Yukarıdaki kod .Net 4.6.1'de bir çalışma zamanı hatası verir. Yanıt düzeltildi.
stop-cran

.NET Framework'ün önceki sürümlerinde, bu özellik
özeldir

Net Core 3.1'de bu benim için işe yaradı. Genel System.Net.ServicePointManager.SecurityProtocol = xxx - ayarının bir paket izlemesinde kesinlikle sıfır etkisi oldu.
Rowan Smith

3

Sadece URI'de HTTPS belirtmek hile yapmalıdır.

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

İstek HTTP ile çalışıyor ancak HTTPS ile başarısız oluyorsa, bu kesinlikle bir sertifika sorunudur . Arayanın sertifika yayıncısına güvendiğinden ve sertifikanın süresinin dolmadığından emin olun. Bunu kontrol etmenin hızlı ve kolay bir yolu, sorguyu bir tarayıcıda yapmayı denemektir.

Ayrıca sunucuda HTTPS isteklerini doğru şekilde sunacak şekilde ayarlandığını (sizinkiyse ve / veya yapabiliyorsanız) kontrol etmek isteyebilirsiniz.


: Benzer bir sorun var: Sorguyu tarayıcıda yaptım ve sertifika geçerli (çağrı geçer, hizmet seviyesi olarak yetkilendirilir ve tüm cazibe gibi çalışır) ama programlı olarak çalışmıyor. Başka ne olabilir? tarayıcıdan "sertifikayı manuel olarak çağırıyor" tarayıcısından srvice'yi programlı olarak çağıran Web Uygulamasından tam olarak aynı sertifikayı kullanırsam?
Carlos

2

Ayrıca hatayı alıyordum:

Temel bağlantı kapatıldı: SSL / TLS güvenli kanalı için güven ilişkisi kurulamadı.

... TLS 1.3 gerektiren bir API sağlayıcısından kaynak istemeye çalışan bir Xamarin Forms Android hedefleme uygulamasıyla .

Çözüm, Xamarin "yönetilen" (.NET) http istemcisini (Xamarin Forms v2.5 itibariyle TLS 1.3'ü desteklemez) değiştirmek ve bunun yerine android yerel istemcisini kullanmak için proje yapılandırmasını güncellemekti.

Görsel stüdyoda basit bir proje geçişi. Aşağıdaki ekran görüntüsüne bakın.

  • Proje Özellikleri
  • Android Seçenekleri
  • ileri
  • Liste öğesi
  • "HttpClient uygulaması" nı "Android" olarak değiştirin
  • SSL / TLS uygulamasını "Yerel TLS 1.2+" olarak değiştirin

resim açıklamasını buraya girin


1

Sınıfınıza aşağıdaki beyanları ekleyin:

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

Sonra:

var client = new HttpClient();

Ve:

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

Mutlu? :)


1

Bu sorunu yaşadım ve benim durumumda çözüm aptalca basitti: Visual Studio'yu Yönetici haklarıyla açın. Yukarıdaki tüm çözümleri denedim ve bunu yapana kadar işe yaramadı. Umarım birine değerli zaman kazandırır.


Sitede yeni olduğunuz için, bir yanıtın yanında yeşil onay işareti varsa, bunun OP tarafından sorunu için doğru çözüm olarak kabul edildiği anlamına gelmeyebilir. Daha iyi, daha eksiksiz bir cevap veremediğiniz sürece, özellikle böyle eski bir soru üzerine başka bir cevap göndermemek en iyisidir.
Sam W

4
Ben de sorunu yaşadım ve yeşil işaretli cevap hiç yardımcı olmadı. Bana yardımcı olan alternatif bir çözüm verdiğimi düşündüm, ama hey, bir dahaki sefere yapmayacağım. Eksi puan için teşekkürler;) harika bir gün var.
Lucian Satmarean

0

ModernHttpClient Nuget Paketini kullanmayı deneyebilirsiniz : Paketi indirdikten sonra şu şekilde uygulayabilirsiniz:

 var handler = new ModernHttpClient.NativeMessageHandler()
 {
     UseProxy = true,
 };


 handler.ClientCertificateOptions = ClientCertificateOption.Automatic;
 handler.PreAuthenticate = true;
 HttpClient client = new HttpClient(handler);

Ne yazık ki, bu benim için işe yaramadı. Çözüm, xamarin yönetilen http istemcisinden android-yerel http istemcisine geçerek TLS 1.3'ü etkinleştirmekti. Cevabımı aşağıda görebilirsiniz.
MSC

0

Felickz katılıyorum ama aynı zamanda c # kullanımını açıklığa kavuşturmak için bir örnek eklemek istiyorum. Windows hizmetinde SSL'yi aşağıdaki gibi kullanıyorum.

    var certificatePath = System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "bin");
    gateway = new GatewayService();
    gateway.PreAuthenticate = true;


    X509Certificate2 cert = new X509Certificate2(certificatePath + @"\Attached\my_certificate.pfx","certificate_password");
    gateway.ClientCertificates.Add(cert);

    ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
    gateway.UserAgent = Guid.NewGuid().ToString();
    gateway.Timeout = int.MaxValue;

Bir web uygulamasında kullanacaksam, sadece proxy tarafında uygulamayı şöyle değiştiriyorum:

public partial class GatewayService : System.Web.Services.Protocols.SoapHttpClientProtocol // to => Microsoft.Web.Services2.WebServicesClientProtocol

-4

Hata için:

Temel bağlantı kapatıldı: SSL / TLS güvenli kanalı için güven ilişkisi kurulamadı.

Aşağıdaki kod ile sertifikayı koşulsuz olarak kabul etmeniz gerektiğini düşünüyorum

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

olarak Karşıt soru verdiği cevap yazdı SSL Web API bağlanırken .NET istemcisi .


4
Bu sertifika doğrulamasını atlıyor. Bunu asla üretimde yapmayın.
John Korsnes

@JohnKorsnes, Abhijeet bazı halka açık WebAPI sunucularına erişiyorsa, bu konuda çok şey yapabileceğini sanmıyorum. Bu benim durumumdu.
Nemanja Simović
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.