リモートサーバーをポーリングし、表示されたとおりにデータを転送する.NET Coreアプリを作成しています。これはPHPで完全に機能しています。なぜなら、PHPはブラウザの問題でもあります)を無視しているからです。しかし、これをC#.NETに移動したいCORE。これはシステム内に残っている唯一のPHP。
サーバーが正常であることはわかっていますが、さまざまな理由により、証明書はすぐに更新できない/更新されません。
リクエストはHttpClientを使用しています:
HttpClient httpClient = new HttpClient();
try
{
string url = "https://URLGoesHere.php";
MyData md = new MyData(); // this is some data we need to pass as a json
string postBody = JsonConvert.SerializeObject(md);
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage wcfResponse = await httpClient.PostAsync(url, new StringContent(postBody, Encoding.UTF8, "application/json"));
Console.WriteLine(wcfResponse.Content);
}
catch (HttpRequestException hre)
{
// This exception is being triggered
}
これを調査した結果、ServicePointManagerを使用することが一般的な推奨事項のようですが、これは.NET Coreでは使用できず、推奨される代替品を見つけることができません。
.NET Coreでこれを行う簡単な方法またはより良い方法はありますか?
new HttpClient()
の代わりに、似たようなものが欲しい
var handler = new System.Net.Http.HttpClientHandler();
using (var httpClient = new System.Net.Http.HttpClient(handler))
{
handler.ServerCertificateCustomValidationCallback = (request, cert, chain, errors) =>
{
// Log it, then use the same answer it would have had if we didn't make a callback.
Console.WriteLine(cert);
return errors == SslPolicyErrors.None;
};
...
}
これは、Windows、およびlibsslがopensslを使用するようにコンパイルされているLinuxで動作するはずです。他のcurlバックエンドでは、Linuxは例外をスローします。
LinuxとmacOSを動作させる
LinuxまたはmacOSで作業している場合、HttpClient
が信頼できるストアにある場合でも自己署名証明書にアクセスできないというシナリオが発生する場合があります。次のものが得られる可能性があります。
_System.Net.Http.CurlException: Peer certificate cannot be authenticated with given CA certificates environment variable
_
(他の回答に示されているように)実装する場合
_handler.ServerCertificateCustomValidationCallback = (request, cert, chain, errors) =>
{
// Log it, then use the same answer it would have had if we didn't make a callback.
Console.WriteLine(cert);
return errors == SslPolicyErrors.None;
};
_
これは、ServerCertificateCustomValidationCallback
を呼び出すための適切なデータを収集するために.Net Coreが必要とする適切なコールバックをサポートしていないマシン上のlibcurlのバージョンが原因です。たとえば、フレームワークがcert
オブジェクトまたは別のパラメーターを作成する方法はありません。詳細については、ドットネットコアのgithubリポジトリで問題となっている.NETコアで提供された回避策の説明を参照してください。
https://github.com/dotnet/corefx/issues/19709
回避策(テストまたは特定の内部アプリケーションにのみ使用する必要があります)は次のとおりです。
_using System;
using System.Net.Http;
using System.Runtime.InteropServices;
namespace netcurl
{
class Program
{
static void Main(string[] args)
{
var url = "https://localhost:5001/.well-known/openid-configuration";
var handler = new HttpClientHandler();
using (var httpClient = new HttpClient(handler))
{
// Only do this for testing and potentially on linux/mac machines
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) && IsTestUrl(url))
{
handler.ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
}
var output = httpClient.GetStringAsync(url).Result;
Console.WriteLine(output);
}
}
static bool IsTestUrl(string url) => url.Contains("localhost");
}
}
_
この問題を修正する別の方法があり、opensslサポートでコンパイルされたlibcurlのバージョンを使用しています。 macOSの場合、これを行う方法に関する優れたチュートリアルを次に示します。
https://spin.atomicobject.com/2017/09/28/net-core-osx-libcurl-openssl/
短いバージョンの場合、opensslサポートでコンパイルされた最新のlibcurlのコピーを取得します。
_brew install curl --with-openssl
_
OS全体でlibcurlのApple以外のバージョンを使用することを強制したくないので、おそらくバイナリを通常のパスに強制的にリンクするためにbrewを使用する代わりに_DYLD_LIBRARY_PATH
_環境変数を使用する必要がありますOSの。
_export DYLD_LIBRARY_PATH=/usr/local/opt/curl/lib${DYLD_LIBRARY_PATH:+:$DYLD_LIBRARY_PATH}
_
上記のコマンドを使用して、ターミナルでdotnet
を実行するときに適切な環境変数を設定できます。ただし、これは実際にはGUIアプリケーションには適用されません。 Visual Studio for Macを使用している場合、プロジェクトの実行設定で環境変数を設定できます。
IdentityServer4とトークン認証を使用する場合、2番目のアプローチが必要でした。 .NET Core 2.0認証パイプラインは、HttpClient
インスタンスを使用してトークン機関への呼び出しを行っていました。 HttpClient
またはそのHttpClientHandler
オブジェクトにアクセスできなかったため、HttpClient
インスタンスに、KeyChainを調べる適切なバージョンのlibcurlを使用するように強制する必要がありました。信頼できる証明書のシステムルート。それ以外の場合、Authorize(AuthenticationSchemes = IdentityServerAuthenticationDefaults.AuthenticationScheme)]
属性を使用してwebapiエンドポイントを保護しようとすると、_System.Net.Http.CurlException: Peer certificate cannot be authenticated with given CA certificates environment variable
_を取得します。
回避策を見つける前にこれを調査するのに何時間も費やしました。私の全体的な目標は、IdentityServer4を使用してwebapiを保護するmacOの開発中に自己署名証明書を使用することでした。お役に立てれば。
//サービスの起動時に、次のコードを追加します
services.AddHttpClient(settings.HttpClientName, client => {
// code to configure headers etc..
}).ConfigurePrimaryHttpMessageHandler(() => {
var handler = new HttpClientHandler();
if (hostingEnvironment.IsDevelopment())
{
handler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => { return true; };
}
return handler;
});
これで、サービス内でIHttpClientFactory CreateClientメソッドを使用できます