让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的GitHub存储库中的问题讨论中找到提供的解决方法。
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))
{
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
您可能不想强制整个操作系统使用非苹果版本的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来保护我的webapi。希望这有所帮助。