[英]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.