SSLを介してWindows 8アプリケーションをテストWeb APIと通信させるのに苦労しています。
HttpClient/HttpClientHandlerは提供せず、WebRequestのような信頼できない証明書を無視するオプションを使用できるようです(ServerCertificateValidationCallback
を使用した「ハッキング」方法でも)。
どんな助けでも大歓迎です!
Windows 8.1では、無効なSSL証明書を信頼できるようになりました。 Windows.Web.HttpClientを使用するか、System.Net.Http.HttpClientを使用する場合は、私が書いたメッセージハンドラーアダプターを使用できます。 http://www.nuget.org/ packages/WinRtHttpClientHandler
ドキュメントはGitHubにあります: https://github.com/onovotny/WinRtHttpClientHandler
迅速で汚い解決策は ServicePointManager.ServerCertificateValidationCallback
デリゲートを使用することです。これにより、独自の証明書検証を提供できます。検証は、アプリドメイン全体にグローバルに適用されます。
ServicePointManager.ServerCertificateValidationCallback +=
(sender, cert, chain, sslPolicyErrors) => true;
これは主に、プロセス中にホストしているエンドポイントに対して実行したい状況で単体テストを行い、 WCFクライアント または HttpClient
でヒットしようとしています。 。
量産コードの場合は、よりきめ細かな制御が必要な場合があり、 WebRequestHandler
とその ServerCertificateValidationCallback
デリゲートプロパティを使用することをお勧めします(下記の dtbの回答 ) 。またはctacke answer を使用して HttpClientHandler
を使用します。統合テストでも、他のフックが見つからない場合を除き、以前の方法よりもこれら2つのいずれかを好んでいます。
WebRequestHandler Class とその ServerCertificateValidationCallback Property をご覧ください。
using (var handler = new WebRequestHandler())
{
handler.ServerCertificateValidationCallback = ...
using (var client = new HttpClient(handler))
{
...
}
}
.NET標準ライブラリでこれを行おうとしている場合、ハンドラーでtrue
を返すだけのすべてのリスクを伴う単純なソリューションがあります。私はあなたに安全を任せます。
var handler = new HttpClientHandler();
handler.ClientCertificateOptions = ClientCertificateOption.Manual;
handler.ServerCertificateCustomValidationCallback =
(httpRequestMessage, cert, cetChain, policyErrors) =>
{
return true;
};
var client = new HttpClient(handler);
または、Windows.Web.Http
名前空間のHttpClientに使用できます。
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)) {
...
}
ここでのほとんどの回答は、典型的なパターンを使用することを示唆しています。
using (var httpClient = new HttpClient())
{
// do something
}
iDisposableインターフェースのため。 しないでください!
マイクロソフトは次の理由を説明します。
そしてここでは、舞台裏で起こっている詳細な分析を見つけることができます: 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;
}
}
}
これがWindowsランタイムアプリケーション用の場合、自己署名証明書をプロジェクトに追加し、appxmanifestで参照する必要があります。
ドキュメントはこちらです: http://msdn.Microsoft.com/en-us/library/windows/apps/hh465031.aspx
信頼されていないCAからのもの(マシン自体が信頼していないプライベートCAなど)の場合も同じです-CAのパブリック証明書を取得し、コンテンツとしてアプリに追加してからマニフェストに追加する必要があります。
それが完了すると、アプリは正しく署名された証明書としてそれを見るでしょう。
答えはありませんが、代替手段はあります。
Fiddler2 を使用してトラフィックを監視し、HTTPS復号化を有効にすると、開発環境で問題が発生することはありません。 Microsoft SurfaceなどのWinRTデバイスでは、標準のアプリをインストールできないため、これは機能しません。しかし、開発Win8コンピューターは問題ありません。
Fiddler2でHTTPS暗号化を有効にするには、Tools> Fiddler Options> HTTPS(Tab)> Check "Decrypt HTTPS Traffic"に移動します。
誰かがエレガントなソリューションを持っていることを期待して、このスレッドに目を光らせていきます。
私はこれで例を見つけました Kubernetes client 彼らが 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>();
}
}
私はオンラインでうまくいくように見える例を見つけました:
まず、新しい 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/