c# - C# 使用 .pem 文件验证服务器证书
问题描述
我发现向启用 SSL 的 API 发送 http 请求时出现问题。我得到的错误信息是 -
AuthenticationException: The remote certificate is invalid according to the validation procedure.
根据这个要求
using (HttpResponseMessage res = client.GetAsync("https://example.com").Result)
{
using (HttpContent content = res.Content)
{
string data = content.ReadAsStringAsync().Result;
if (data != null)
{
Console.WriteLine(data);
}
else
{
Console.WriteLine("Nothing returned");
}
}
}
我已经获得了一个 .pem 文件来验证发回的证书是否由我们的 CA 签名,并且在弄清楚如何在 C# 中执行此操作时遇到了一些麻烦
在python中,我可以通过将.pem文件传递给验证参数来解决证书错误,例如
r = requests.post(url="https://example.com", headers=headers, verify='mypem.pem')
Dotnet Core 3 的 HttpClient 中是否有等价的东西?
感谢您的帮助!
解决方案
如果由于某种原因您无法将证书设置为受信任,那么您可以绕过证书验证并自己验证服务器。不幸的是,它在 .NET 中的优雅程度要低得多,而且这可能不适用于所有平台。有关更多讨论,请参阅有关在 .net 核心中绕过无效 SSL 证书的答案。
using (var httpClientHandler = new HttpClientHandler())
{
// Override server certificate validation.
httpClientHandler.ServerCertificateCustomValidationCallback = VerifyServerCertificate;
// ^ if this throws PlatformNotSupportedException (on iOS?), then you have to use
//httpClientHandler.ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
// ^ docs: https://docs.microsoft.com/en-us/dotnet/api/system.net.http.httpclienthandler.dangerousacceptanyservercertificatevalidator?view=netcore-3.0
using (var client = new HttpClient(httpClientHandler))
{
// Make your request...
}
}
我认为回调的这种实现可以满足您的需求,“固定” CA。从这个答案到Force HttpClient to trust single Certificate,还有我的更多评论。 编辑:该答案的状态检查不起作用,但根据Jeremy Farmer 链接的这个答案,以下方法应该:
static bool VerifyServerCertificate(HttpRequestMessage sender, X509Certificate2 certificate,
X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
try
{
// Possibly required for iOS? :
//if (chain.ChainElements.Count == 0) chain.Build(certificate);
// https://forums.xamarin.com/discussion/180066/httpclienthandler-servercertificatecustomvalidationcallback-receives-empty-certchain
// ^ Sorry that thread is such a mess! But please check it.
// Without having your PEM I am not sure if this approach to loading the cert works, but there are other ways. From the doc:
// "This constructor creates a new X509Certificate2 object using a certificate file name. It supports binary (DER) encoding or Base64 encoding."
X509Certificate2 ca = new X509Certificate2("mypem.pem");
X509Chain chain2 = new X509Chain();
chain2.ChainPolicy.ExtraStore.Add(ca);
// "tell the X509Chain class that I do trust this root certs and it should check just the certs in the chain and nothing else"
chain2.ChainPolicy.VerificationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority;
// This setup does not have revocation information
chain2.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
// Build the chain and verify
var isValid = chain2.Build(certificate);
var chainRoot = chain2.ChainElements[chain2.ChainElements.Count - 1].Certificate;
isValid = isValid && chainRoot.RawData.SequenceEqual(ca.RawData);
Debug.Assert(isValid == true);
return isValid;
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
return false;
}
抱歉,我目前无法对此进行测试,但希望对您有所帮助。
推荐阅读
- r - 通过变量的唯一组合将变量添加到分组数据
- typescript - 黄瓜的纽约运行时覆盖率
- javascript - 发送多张图片但只显示一张
- excel - VBA 中 Microsoft Office 实例之间的通信
- python-3.x - 如何在pytorch中升级图像?
- r - 使用 ifelse 安装包
- android - NavigationDrawer 菜单中的 ScrollView
- .net - StackExchange Redis AddOrUpdate 处理(乐观并发)
- cmake - 在模板文件中扩展变量、#cmakedefine 和生成器表达式
- node.js - 多对多模型 A 未使用 Sequelize 关联到模型 B