HttpClientを使用してHttps呼び出しを行う


157

私はHttpClientC#を使用してWebApi呼び出しを行うために使用しています。に比べてすっきりと速い方法のようWebClientです。しかし、Https電話をしている間に立ち往生しています。

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

編集1: 上記のコードはhttp呼び出しを行うために正常に動作します。しかし、スキームをhttpsに変更すると機能しません。取得したエラーは次のとおりです。

基になる接続が閉じられました:SSL / TLSセキュアチャネルの信頼関係を確立できませんでした。

編集2: スキームをhttpsに変更するには、ステップ1を実行します。

C#リクエストと共に証明書と公開鍵/秘密鍵を提供するにはどうすればよいですか。


2
指定するだけでhttps呼び出しを行っているnew Uri("https://foobar.com/");
felickz '

2
よくわかりません。それはまだ動作しませんか?エラーが発生していますか?(編集:OPがURIをhttpsからhttpに変更する前に投稿)
Tim

回答:


215

サーバーがTLS 1.2のようなより高いTLSバージョンのみをサポートしている場合でも、クライアントPCがデフォルトでより高いTLSバージョンを使用するように構成されていない限り、サーバーは失敗します。この問題を解決するには、コードに以下を追加します。

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

サンプルコードを変更すると、

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よろしくお願いします。なんらかの理由で、プロダクション設定のコードを変更できないが、サーバーで何らかの管理を実行できる場合は、このユーティリティを使用してTLS 1.2をデフォルトとして構成します。nartac.com/Products/IISCrypto
Ronald Ramos

SecurityProtocolType.Tls12あなたが言及した列挙値を見つけることができません
でした

1
@JobaDinizは.NET 4.5以降を使用し、System.Net名前空間を含みます。
ロナルドラモス2016

SecurityProtocolの設定は一度だけ行う必要がありますか?アプリケーションの起動時のように?
CamHart

これはうまくいきます。ありがとう。また、このHttpClient client = new HttpClient();を使用するヘッダーをクリアする必要がないこともわかりました。ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls; HttpResponseMessage response = await client.GetAsync( "https:// ...");
AtLeastTheresToast

127

URIにHTTPSを指定するだけです。

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

Foobar.comには信頼できるSSL証明書が必要です。そうでない場合、呼び出しは信頼できないエラーで失敗します。

回答を編集:HttpClientによるClientCertificates

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

回答2の編集:接続先のサーバーでSSL、TLS 1.0、および1.1が無効になっていて、.NET Framework 4.5(またはそれ以下)をまだ実行している場合は、選択する必要があります

  1. .Net 4.6+にアップグレード(デフォルトでTLS 1.2をサポート
  2. レジストリの変更を追加して、TLS1.2経由で接続するように4.5に指示します(参照:変更のための互換性とキーのセールスフォースの書き込みまたはIISCryptoのチェックアウトロナルドラモスの回答のコメントを参照)
  3. TLS1.2経由で接続するように.NETを手動で構成するアプリケーションコードを追加します(Ronald Ramosの回答を参照)

@felickz素晴らしい反応。Windows Phone 8のWebRequestHandlerライブラリに相当するものはありますか?
Billatron 2014年

@Billatron WP / Win8のさまざまなライブラリ.. 参照
felickz

6
開発または自己署名本命を扱うときには、次のと信頼できない証明書エラーを無視することができます: ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;
開発者

6
なにGetMyX509Certificate
Fandi Susanto 2016年

6
@developerは、コードが本番ビルドに組み込まれないことを望みます:)
felickz

15

コードは次のように変更する必要があります。

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

https:URIスキームを使用する必要があります。便利なページがあります、ここでセキュアなHTTP接続についてMSDNに。確かに:

https:URIスキームを使用する

HTTPプロトコルは2つのURIスキームを定義します。

http:暗号化されていない接続に使用されます。

https:暗号化する必要がある安全な接続に使用されます。このオプションでは、デジタル証明書と認証局を使用して、サーバーが本人であることを確認します。

さらに、HTTPS接続はSSL証明書を使用することを考慮してください。安全な接続にこの証明書があることを確認してください。そうでない場合、リクエストは失敗します。

編集:

上記のコードは、http呼び出しを行うために正常に動作します。しかし、スキームをhttpsに変更すると機能しません。エラーを投稿します。

機能しないのはどういう意味ですか?リクエストは失敗しますか?例外がスローされますか?質問を明確にしてください。

要求が失敗した場合、問題はSSL証明書であるはずです。

問題を修正するには、クラスHttpWebRequestを使用してから、そのプロパティを使用しますClientCertificate。さらに、証明書を使用してHTTPSリクエストを作成する方法に関する便利なサンプルをここで見つけることができます。

例は次のとおりです(前にリンクされたMSDNページに示されています)。

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

正確には、トリックは要求とともに証明書を送信することにあります。どうやってするか?
Abhijeet 14年

「C:\\ mycert.cer」はどこで入手できますか?mycert.cerファイルを生成するには?
masiboo 2018

@masiboo私が書いたものは、HTTPS呼び出しを行う方法の回答です。* .cerファイルの生成方法についてグーグルに尋ねると、自分で答えを見つけることができます。
アルベルトソラーノ

9

接続するときhttpsにもこのエラーが発生した場合は、前にこの行を追加HttpClient httpClient = new HttpClient();して正常に接続します。

ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };

私はこの回答別の類似のAnwserとコメントの言及からそれを知っています:

これは開発に役立つハックです。そのため#if DEBUG #endifステートメントを配置することは、これを安全にして本番環境で終了するのを防ぐために最低限行うべきです

その上、私は別の回答で証明書を使用new X509Certificate()またはnew X509Certificate2()作成する方法を試していませnew()んでした。単に作成者が機能するかどうかはわかりません。

編集: いくつかの参照:

IIS 7で自己署名サーバー証明書を作成する

IIS 7でSSL証明書をインポートおよびエクスポートする

.pfxを.cerに変換する

ServerCertificateValidationCallbackを使用するためのベストプラクティス

Thumbprintの値が次と等しいことがわかりましたx509certificate.GetCertHashString()

証明書の拇印を取得する


6

ユーザーエージェントを必要とするGitHubへの接続時にも同じ問題が発生しました。したがって、証明書を生成するのではなく、これを提供するだけで十分です。

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
インターネットで共有しているトークンを取り消す必要があります。GitHubが自動的に行った可能性があります。
Amias

21
本当に私のトークンはで始まると思います123456789か?
カルロV.ダンゴ

5

のレベルに非グローバル設定がありますHttpClientHandler

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

var client = new HttpClient(handler);

したがって、最新のTLSバージョンを有効にします。

デフォルト値SslProtocols.Defaultは実際にはSslProtocols.Ssl3 | SslProtocols.Tls(.Net Core 2.1および.Net Framework 4.7.1でチェックされている)ことに注意してください。


答えてくれてありがとう。少し注意:このドキュメントのとおり:docs.microsoft.com/en-us/dotnet/api/…少なくともフレームワーク4.7.1が必要です。
GELR

@GELRはい、そうです。上記のコードは、.Net 4.6.1で実行時エラーを生成します。答えを修正しました。
stop-cran

以前のバージョンの.NET Frameworkでは、このプロパティはプライベートです
JotaBe

Net Core 3.1では、これですべてうまくいきました。グローバルSystem.Net.ServicePointManager.SecurityProtocol = xxxを設定すると、パケットトレースにまったく影響がありませんでした。
Rowan Smith

3

URIにHTTPSを指定するだけでうまくいくはずです。

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

リクエストがHTTPで機能し、HTTPSで失敗する場合、これは間違いなく証明書の問題です。呼び出し元が証明書の発行者を信頼していること、および証明書の有効期限が切れていないことを確認してください。これをすばやく簡単に確認する方法は、ブラウザでクエリを作成することです。

また、HTTPSリクエストを適切に処理するように設定されていることをサーバーで確認することもできます(サーバーが自分のものであるか、または可能かどうか)。


:私は同様の問題があります:ブラウザーでクエリを実行しましたが、証明書は有効です(コールパススルー、サービスレベルとして承認され、すべてチャームのように機能します)が、プログラムでは機能しません。他に何ができますか?ブラウザからプログラムでサービスを呼び出すWebアプリケーションからのものとまったく同じ証明書を使用する場合
カルロス、

2

私もエラーを得ていました:

基になる接続が閉じられました:SSL / TLSセキュアチャネルの信頼関係を確立できませんでした。

... Xamarin Forms Androidをターゲットとするアプリケーションが、TLS 1.3を必要とするAPIプロバイダーにリソースをリクエストしようとした場合

解決策は、Xamarinの「管理対象」(.NET)httpクライアント(Xamarin Forms v2.5ではTLS 1.3をサポートしていない)を交換するようにプロジェクト構成を更新し、代わりにAndroidネイティブクライアントを使用することでした。

Visual Studioでの単純なプロジェクト切り替えです。下のスクリーンショットを参照してください。

  • プロジェクトのプロパティ
  • Androidオプション
  • 高度な
  • リストアイテム
  • 「HttpClient実装」を「Android」に変更
  • SSL / TLS実装を「ネイティブTLS 1.2+」に変更します

ここに画像の説明を入力してください


1

以下の宣言をクラスに追加します。

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

後:

var client = new HttpClient();

そして:

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

ハッピー?:)


1

私にはこの問題があり、私の場合、解決策は愚かなほど単純でした:管理者権限でVisual Studioを開きます。私は上記の解決策をすべて試しましたが、これを行うまで機能しませんでした。誰かが貴重な時間を節約できることを願っています。


サイトに不慣れなので、回答の横に緑色のチェックマークが付いている場合、OPが問題の正しい解決策としてそれを受け入れたことを意味します。より適切で完全な回答を提供できない限り、特にそのような古い質問では、別の回答を送信しないことがおそらく最善です。
Sam W

4
まあ、私も問題があり、緑のチェックされた答えはまったく役に立ちませんでした。私に役立つ別の解決策を提供すると思いましたが、ちょっと、次回は行いません。マイナスポイントをありがとう;)素晴らしい一日を。
Lucian Satmarean

0

ModernHttpClient Nugetパッケージを使用してみることができます。パッケージをダウンロードした後、次のように実装できます。

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


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

残念ながら、これではうまくいきませんでした。ソリューションは、xamarinで管理されたhttpクライアントからandroid-native httpクライアントに切り替えることにより、TLS 1.3を有効にすることでした。以下の私の答えを参照してください。
MSC

0

私はfelickzに同意しますが、c#での使用法を明確にするための例も追加したいと思います。以下のように、WindowsサービスでSSLを使用しています。

    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;

Webアプリケーションで使用する場合は、次のようにプロキシ側の実装を変更するだけです。

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

-4

エラーの場合:

基になる接続が閉じられました:SSL / TLSセキュアチャネルの信頼関係を確立できませんでした。

次のコードで無条件に証明書を受け入れる必要があると思います

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

反抗質問に彼の答えに書いたSSLのWeb APIに接続する.NETクライアント


4
これは証明書の検証をバイパスしています。本番環境ではこれを行わないでください。
John Korsnes

@JohnKorsnesさん、AbhijeetがパブリックWebAPIサーバーにアクセスしている場合、彼がそれについて多くのことを行えるとは思いません。これは私のケースでした。
NemanjaSimović2018
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.