[英]Ignore bad certificate - .NET CORE
我正在編寫一個 .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 和 Linux,其中 libcurl 被編譯為使用 openssl。 對於其他 curl 后端,Linux 會拋出異常。
//在啟動配置服務時添加以下代碼
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 方法
讓 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;
};
這是因為機器上的 libcurl 版本不支持 .Net Core 需要的適當回調,以便收集適當的數據以調用ServerCertificateCustomValidationCallback
。 例如,框架沒有辦法創建cert
對象或另一個參數。 更多信息可以在 .NET Core 中提供的解決方法的討論中找到,在 dotnet core 的 github repo 中有問題:
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
您可能不想強制整個操作系統使用非 Apple 版本的 libcurl,因此您可能希望使用DYLD_LIBRARY_PATH
環境變量而不是使用 brew 強制將二進制文件鏈接到操作系統的常規路徑。
export DYLD_LIBRARY_PATH=/usr/local/opt/curl/lib${DYLD_LIBRARY_PATH:+:$DYLD_LIBRARY_PATH}
上述命令可用於在終端中運行dotnet
時設置適當的環境變量。 但這並不真正適用於 GUI 應用程序。 如果您使用的是 Visual Studio for Mac,則可以在項目運行設置中設置環境變量:
在使用 IdentityServer4 和令牌授權時,第二種方法對我來說是必要的。 .NET Core 2.0 授權管道正在使用HttpClient
實例調用令牌授權。 由於我無權訪問HttpClient
或其HttpClientHandler
對象,因此我需要強制HttpClient
實例使用合適的 libcurl 版本,以便查看我的 KeyChain 系統根目錄以獲得我的受信任證書。 否則,在嘗試使用Authorize(AuthenticationSchemes = IdentityServerAuthenticationDefaults.AuthenticationScheme)]
屬性保護 webapi 端點時,我會得到System.Net.Http.CurlException: Peer certificate cannot be authenticated with given CA certificates environment variable
。
在找到解決方法之前,我花了幾個小時研究這個。 我的整個目標是在使用 IdentityServer4 的 macO 開發過程中使用自簽名證書來保護我的 webapi。 希望這可以幫助。
只是為了添加另一個變體,您可以添加指紋並在回調中檢查它以使事情更安全,例如:
if (!string.IsNullOrEmpty(adminConfiguration.DevIdentityServerCertThumbprint))
{
options.BackchannelHttpHandler = new HttpClientHandler
{
ServerCertificateCustomValidationCallback = (sender, certificate, chain, sslPolicyErrors) => certificate.Thumbprint.Equals(adminConfiguration.DevIdentityServerCertThumbprint, StringComparison.InvariantCultureIgnoreCase)
};
}
adminConfiguration.DevIdentityServerCertThumbprint
是您將使用自簽名證書的指紋設置的配置。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.