问题描述
我需要信任应用程序中的一些自签名证书,所以我像这样覆盖验证回调:
I need to trust some self-signed certificates in the application, so I override validation callback like this:
ServicePointManager.ServerCertificateValidationCallback = MyRemoteCertificateValidationCallback;
...
public static bool MyRemoteCertificateValidationCallback(
Object sender,
X509Certificate certificate,
X509Chain chain,
SslPolicyErrors sslPolicyErrors)
{
if (sslPolicyErrors == SslPolicyErrors.None)
return true;
if (IsAprrovedByMyApplication(sender, certificate)) // <-- no matter what the check here is
return true;
else
return false; // <-- here I'd like to call the default Windows handler rather than returning 'false'
}
但是当有一些策略错误,并且我连接的站点没有被应用程序批准时,就会抛出异常.这里的问题是它不同于标准的 Windows 行为.
But when there're some policy errors, and the site I am connecting to is not approved by application, the Exception is thrown. The problem here is that it differs from standard Windows behavior.
考虑这个网站:https://www.dscoduc.com/
它的证书有一个未知的颁发者,因此不受信任.我已将它与 MMC 一起添加到本地计算机的受信任的人(它是 Windows 7).
It's certificate has an unknown issuer, and therefore untrusted. I have added it with MMC to the Local Computer's Trusted People (it's Windows 7).
如果我在不覆盖证书验证回调的情况下运行此代码:
If I run this code without overriding certificate validation callback:
HttpWebRequest http = (HttpWebRequest)HttpWebRequest.Create("https://www.dscoduc.com/");
using (WebResponse resp = http.GetResponse())
{
using (StreamReader sr = new StreamReader(resp.GetResponseStream()))
{
string htmlpage = sr.ReadToEnd();
}
}
连接成功.这意味着 Windows 默认验证器决定信任此证书.
但是一旦我覆盖了 ServerCertificateValidationCallback,我的回调就会被调用 SslPolicyErrors.RemoteCertificateChainErrors并且链包含一个状态为 X509ChainStatusFlags.PartialChain 的元素(实际上我希望这里不会收到任何错误,因为当前的证书应该是可信的)
But once I override the ServerCertificateValidationCallback, my callback is called with SslPolicyErrors.RemoteCertificateChainErrors and the chain contains one element with status X509ChainStatusFlags.PartialChain (in fact I would expect to receive no errors here, because current cert is supposed to be trusted)
此站点未包含在我的信任列表中,并且不想从我的回调中返回true".但是我也不想返回'false',否则我会得到一个异常:远程证书根据验证程序无效",这显然不是 https://www.dscoduc.com/,因为它已添加到受信任的人存储中,并且在证书回调未被覆盖时由 Windows 批准.因此,我希望 Windows 采用该站点的默认验证程序.我不想亲自查看 Windows 受信任的商店并查看所有链元素,因为它已经(并且希望正确)在 Windows 中实现.
This site is not included in my trusted list, and do not want to return 'true' from my callback. But I don't want to return 'false' neither, or I'll get an Exception: "The remote certificate is invalid according to the validation procedure", which is obviously not expected for https://www.dscoduc.com/, because it's added to Trusted People store, and is approved by Windows when certificate callback is not overridden. So I want Windows to take the default validation procedure for this site. I don't want to look into Windows Trusted stores myself and go through all the chain elements, because it's already (and hopefully correctly) implemented in Windows.
换句话说,我需要明确信任用户批准的网站(存储在他的设置中的某处),并为所有其他网站调用默认认证检查.
ServicePointManager.ServerCertificateValidationCallback 的默认值为 null,因此没有默认"回调供我稍后调用.我应该如何调用这个默认"证书处理程序?
The default value for ServicePointManager.ServerCertificateValidationCallback is null, so there's no 'default' callback for me to call later. How should I call this 'default' certificate handler?
推荐答案
这样的事情可能会奏效.请注意,X509CertificateValidator 允许您选择是否在验证中包含 Trusted People 存储.
Something like this might work. Note the X509CertificateValidator allows you to choose whether to include the Trusted People store in the validation.
private static bool CertificateValidationCallBack(
object sender,
X509Certificate certificate,
X509Chain chain,
SslPolicyErrors sslPolicyErrors)
{
// Your custom check here...
if (isYourSpecialCase)
{
return true;
}
// If it is not your special case then revert to default checks...
// Convert the certificate to a X509Certificate2
var certificate2 = certificate as X509Certificate2 ?? new X509Certificate2(certificate);
try
{
// Choose the type of certificate validation you want
X509CertificateValidator.PeerOrChainTrust.Validate(certificate2);
//X509CertificateValidator.ChainTrust.Validate(certificate2);
}
catch
{
return false;
}
// Sender is always either a WebReqest or a hostname string
var request = sender as WebRequest;
string requestHostname = request != null ? request.RequestUri.Host : (string)sender;
// Get the hostname from the certificate
string certHostname = certificate2.GetNameInfo(X509NameType.DnsName, false);
return requestHostname.Equals(certHostname, StringComparison.InvariantCultureIgnoreCase);
}
这篇关于在 C# 中覆盖 ServicePointManager.ServerCertificateValidationCallback 时如何调用默认证书检查?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!