HttpClientによる信頼されていないSSL証明書の許可


114

私のWindows 8アプリケーションがSSLを介してテストWeb APIと通信するのに苦労しています。

HttpClient / HttpClientHandlerはWebRequestのような信頼できない証明書を無視するオプションを提供していないようです(ただし、を使用して「ハック」な方法でServerCertificateValidationCallback)。

どんな助けでも大歓迎です!


5
.NET Coreを使用している場合は、この答えに興味があるかもしれません。
kdaveid 2017年

回答:


13

Windows 8.1では、無効なSSL証明書を信頼できるようになりました。Windows.Web.HttpClientを使用する必要があります。または、System.Net.Http.HttpClientを使用する場合は、私が書いたメッセージハンドラーアダプターを使用できます。http//www.nuget.org/packages/WinRtHttpClientHandler

ドキュメントはGitHubにあります:https : //github.com/onovotny/WinRtHttpClientHandler


12
すべてのコードを使用せずにこれを行う方法はありますか?言い換えれば、あなたの解決策の要点は何ですか?
wensveen 2015

ソリューションの要点は、Windows httpクライアントハンドラーをラップし、それをHttpClientの実装として使用することです。それはすべてこのファイルにあります:github.com/onovotny/WinRtHttpClientHandler/blob/master/…自由にコピーしてくださいが、パッケージを使用しない理由はわかりません。
Claire Novotny、2015年

@OrenNovotnyなので、ソリューションはWindowsバージョンにバインドされていませんか?
chester89

これをUWPアプリに実装し、以下のフィルターの例を使用しました。それでも同じエラーが発生します。
クリスチャンフィンドレイ

158

デリケートを使用すると、すばやく簡単に解決できますServicePointManager.ServerCertificateValidationCallback。これにより、独自の証明書検証を提供できます。検証は、アプリドメイン全体にグローバルに適用されます。

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

私は主に、進行中のホストしているエンドポイントに対して実行したい状況でユニットテストに使用し、WCFクライアントまたはでヒットさせようとしていHttpClientます。

プロダクションコードの場合は、より細かい制御が必要になる場合があり、WebRequestHandlerおよびそのServerCertificateValidationCallbackデリゲートプロパティを使用した方がよいでしょう(下のdtbの回答を参照)。または、を使用して答えを入力しHttpClientHandlerます。他のフックが見つからない場合を除いて、以前の方法よりも統合テストを行った場合でも、これら2つのうちのいずれかを使用することを好みます。


32
反対投票ではありませんが、ServerCertificateValidationCallbackの最大の問題の1つは、基本的にAppDomainに対してグローバルであることです。したがって、信頼されていない証明書を使用してサイトを呼び出す必要があるライブラリを作成し、この回避策を採用している場合は、ライブラリだけでなく、アプリケーション全体の動作を変更しています。また、人々は常に「盲目的に真実を返す」アプローチに注意する必要があります。これはセキュリティに深刻な影響を及ぼします。/ *を読んで、指定されたパラメーターを検査し、* /を返すかどうかを慎重に決定する必要があります。
scottt732 2014年

@ scottt732確かに有効な点であり、言及する価値がありますが、それでも有効な解決策です。おそらく、OPによる元の質問を再度読んだ後、ServerCertificateValidationCallbackハンドラーをすでに認識していたようです
Bronumski

2
少なくとも送信者のようないくつかの基準でフィルタリングすることをお勧めします
Boas Enkler

2
グローバルなServicePointManagerではなく、WebRequestHandlerオプションを推奨する必要があります。
トーマスS.トリアス2016

3
ServicePointManagerをグローバルに使用する必要はありません。使用してServicePointManager.GetServicePoint(Uri)docsを参照)、そのURIへの呼び出しにのみ適用されるサービスポイントを取得できます。次に、そのサブセットに基づいてプロパティを設定し、イベントを処理できます。
oatsoda

87

WebRequestHandlerクラスとそのServerCertificateValidationCallbackプロパティを見てください。

using (var handler = new WebRequestHandler())
{
    handler.ServerCertificateValidationCallback = ...

    using (var client = new HttpClient(handler))
    {
        ...
    }
}

5
回答をありがとうございましたが、すでに調べましたが、Windows 8ストアアプリの.NETにはありません。
ジェイミー

ただし、独自のHttpClientHandlerまたはHttpMessageHandler派生クラスを作成することは、特にWebRequestHandlerソースがすぐに利用できるという事実を考えると、十分簡単です。
トーマスS.トリアス2016

@ ThomasS.Triasそれに関するサンプルはありますか?derived class
Kiquenet 2018年

2
使い方HttpClientHandler
Kiquenet 2018年

1
@Kiquenetこの返信は2012年のもので、すでに6歳です。そうです-多くの人は、これがhttpclientを使用する正しい方法であると確信していました:)
justmara

63

.NET標準ライブラリでこれを実行しようとしている場合trueは、ハンドラーに戻るだけのリスクをすべて伴う、簡単な解決策を次に示します。安全はあなた次第です。

var handler = new HttpClientHandler();
handler.ClientCertificateOptions = ClientCertificateOption.Manual;
handler.ServerCertificateCustomValidationCallback = 
    (httpRequestMessage, cert, cetChain, policyErrors) =>
{
    return true;
};

var client = new HttpClient(handler);

1
これにより、uwpから参照したときにプラットフォームがサポートされなくなります
Ivan

UWPで私のために働いた。おそらく、サポート範囲は14か月で成熟しています。注:このハックはtest / dev envでのみ必要です(自己署名証明書が使用されている場合)
Ben McIntyre

私はこのコードを実行し、常にSystem.NotImplementedExceptionを満たしました。理由はわかりません。
劉鳳

25

または、名前空間のHttpClientに使用できWindows.Web.Httpます。

var filter = new HttpBaseProtocolFilter();
#if DEBUG
    filter.IgnorableServerCertificateErrors.Add(ChainValidationResult.Expired);
    filter.IgnorableServerCertificateErrors.Add(ChainValidationResult.Untrusted);
    filter.IgnorableServerCertificateErrors.Add(ChainValidationResult.InvalidName);
#endif
using (var httpClient = new HttpClient(filter)) {
    ...
}

私は使用することができSystem.Net.HttpSystem.WebそしてWindows.Web.Http一緒に?
Kiquenet 2018年

2
HttpClientは、.NET StandardまたはUWPでこのオーバーライドが行われていないようです。
クリスチャンフィンドリー

:「使用」のパターンを使用しないでくださいdocs.microsoft.com/en-us/azure/architecture/antipatterns/...
ベルンハルト

15

あなたが使用しSystem.Net.Http.HttpClientている場合、正しいパターンは

var handler = new HttpClientHandler() 
{ 
    ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator
};

var http = new HttpClient(handler);
var res = http.GetAsync(url);

8

ここでのほとんどの回答は、典型的なパターンを使用することを提案しています:

using (var httpClient = new HttpClient())
{
 // do something
}

IDisposableインターフェイスのため。しないでください!

Microsoftが理由を説明します。

そしてここでは、舞台裏で起こっている詳細な分析を見つけることができます:https : //aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/

SSLの質問について、およびhttps://docs.microsoft.com/en-us/azure/architecture/antipatterns/improper-instantiation/#how-to-fix-the-problemに基づいて

ここにあなたのパターンがあります:

class HttpInterface
{
 // https://docs.microsoft.com/en-us/azure/architecture/antipatterns/improper-instantiation/#how-to-fix-the-problem
 // https://docs.microsoft.com/en-us/dotnet/api/system.net.http.httpclient#remarks
 private static readonly HttpClient client;

 // static initialize
 static HttpInterface()
 {
  // choose one of these depending on your framework

  // HttpClientHandler is an HttpMessageHandler with a common set of properties
  var handler = new HttpClientHandler();
  {
      ServerCertificateCustomValidationCallback = delegate { return true; },
  };
  // derives from HttpClientHandler but adds properties that generally only are available on full .NET
  var handler = new WebRequestHandler()
  {
      ServerCertificateValidationCallback = delegate { return true; },
      ServerCertificateCustomValidationCallback = delegate { return true; },
  };

  client = new HttpClient(handler);
 }

 .....

 // in your code use the static client to do your stuff
 var jsonEncoded = new StringContent(someJsonString, Encoding.UTF8, "application/json");

 // here in sync
 using (HttpResponseMessage resultMsg = client.PostAsync(someRequestUrl, jsonEncoded).Result)
 {
  using (HttpContent respContent = resultMsg.Content)
  {
   return respContent.ReadAsStringAsync().Result;
  }
 }
}

問題は、自己署名証明書の信頼関係です。あなたの全体の答えは、HttpClientスレッドを安全にすることです(それが有効だと考えられていても)。
Adarsha

1
「スレッドの安全性」だけではありません。「無効な」SSL検証を使用したhttpclientの「正しい」使用方法を示したかったのです。他の答えは、「グローバルに」証明書マネージャーを変更します。
ベルンハルト

7

これがWindowsランタイムアプリケーションの場合は、自己署名証明書をプロジェクトに追加し、appxmanifestで参照する必要があります。

ドキュメントはこちら:http : //msdn.microsoft.com/en-us/library/windows/apps/hh465031.aspx

信頼されていないCAからのものである場合も同じです(マシン自体が信頼しないプライベートCAなど)。CAの公開証明書を取得し、コンテンツとしてアプリに追加して、マニフェストに追加する必要があります。

これが完了すると、アプリはそれを正しく署名された証明書として表示します。


2

答えはありませんが、別の方法があります。

あなたが使用している場合はFiddler2をするトラフィックを監視し、HTTPS復号化を可能にするために、開発環境は文句を言わないだろう。Microsoft SurfaceなどのWinRTデバイスでは、標準のアプリをインストールできないため、これは機能しません。しかし、あなたの開発Win8コンピュータは大丈夫でしょう。

Fiddler2でHTTPS暗号化を有効にするには、[ツール]> [Fiddlerオプション]> [HTTPS(タブ)]> [HTTPSトラフィックの復号化]をオンにします

私は誰かがエレガントな解決策を持っていることを期待してこのスレッドに目を離さないつもりです。


2

このKubernetesクライアントで、X509VerificationFlags.AllowUnknownCertificateAuthorityを使用して自己署名の自己署名ルート証明書を信頼する例を見つけました。独自のPEMエンコードされたルート証明書で動作するように、それらの例を少し修正しました。うまくいけば、これは誰かを助けます。

namespace Utils
{
  using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Net.Security;
  using System.Security.Cryptography.X509Certificates;

  /// <summary>
  /// Verifies that specific self signed root certificates are trusted.
  /// </summary>
  public class HttpClientHandler : System.Net.Http.HttpClientHandler
  {
    /// <summary>
    /// Initializes a new instance of the <see cref="HttpClientHandler"/> class.
    /// </summary>
    /// <param name="pemRootCerts">The PEM encoded root certificates to trust.</param>
    public HttpClientHandler(IEnumerable<string> pemRootCerts)
    {
      foreach (var pemRootCert in pemRootCerts)
      {
        var text = pemRootCert.Trim();
        text = text.Replace("-----BEGIN CERTIFICATE-----", string.Empty);
        text = text.Replace("-----END CERTIFICATE-----", string.Empty);
        this.rootCerts.Add(new X509Certificate2(Convert.FromBase64String(text)));
      }

      this.ServerCertificateCustomValidationCallback = this.VerifyServerCertificate;
    }

    private bool VerifyServerCertificate(
      object sender,
      X509Certificate certificate,
      X509Chain chain,
      SslPolicyErrors sslPolicyErrors)
    {
      // If the certificate is a valid, signed certificate, return true.
      if (sslPolicyErrors == SslPolicyErrors.None)
      {
        return true;
      }

      // If there are errors in the certificate chain, look at each error to determine the cause.
      if ((sslPolicyErrors & SslPolicyErrors.RemoteCertificateChainErrors) != 0)
      {
        chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;

        // add all your extra certificate chain
        foreach (var rootCert in this.rootCerts)
        {
          chain.ChainPolicy.ExtraStore.Add(rootCert);
        }

        chain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority;
        var isValid = chain.Build((X509Certificate2)certificate);

        var rootCertActual = chain.ChainElements[chain.ChainElements.Count - 1].Certificate;
        var rootCertExpected = this.rootCerts[this.rootCerts.Count - 1];
        isValid = isValid && rootCertActual.RawData.SequenceEqual(rootCertExpected.RawData);

        return isValid;
      }

      // In all other cases, return false.
      return false;
    }

    private readonly IList<X509Certificate2> rootCerts = new List<X509Certificate2>();
  }
}

1

私はうまくいくように見えるオンラインの例を見つけました:

まず、新しいICertificatePolicyを作成します

using System.Security.Cryptography.X509Certificates;
using System.Net;

public class MyPolicy : ICertificatePolicy
{
  public bool CheckValidationResult(ServicePoint srvPoint, X509Certificate certificate, WebRequest request, 
int certificateProblem)
  {
    //Return True to force the certificate to be accepted.
    return true;
  }
}

次に、次のようにhttpリクエストを送信する前にこれを使用します。

System.Net.ServicePointManager.CertificatePolicy = new MyPolicy();

http://www.terminally-incoherent.com/blog/2008/05/05/send-a-https-post-request-with-c/


1
ServicePointManager.CertificatePolicy廃止されました:docs.microsoft.com/en-us/dotnet/framework/whats-new/...
schmidlop
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.