C# 还原SSL证书覆盖检查
我正在编写一个测试来测试我正在部署的服务,为了绕过ssl证书检查,我使用以下代码段实现了ssl覆盖:C# 还原SSL证书覆盖检查,c#,C#,我正在编写一个测试来测试我正在部署的服务,为了绕过ssl证书检查,我使用以下代码段实现了ssl覆盖: public static void SSLValidationOverride() { ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(OnValidationCallba
public static void SSLValidationOverride()
{
ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(OnValidationCallback);
}
private static bool OnValidationCallback(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors errors)
{
if (cert.subject == MyCertSubject)
return true;
else
return false;
}
现在,我必须在代码中使用ssl调用另一个Web服务,并希望在调用该服务之前切换到默认ssl检查。最好的方法是什么。MS help表示ServicePointManager.SecurityProtocol的默认值为null()。将其设置为null将切换到默认ssl验证,是否有其他方法来执行此操作。我最终将ServicePointManager.SecurityProtocol设置为null,它工作正常。虽然我仍然愿意用更好的方法来做到这一点
public static void SSLValidationRestore()
{
ServicePointManager.ServerCertificateValidationCallback = null;
}
将回调设置为null无效。相反,所有证书都通过。我不明白为什么有那么多人发布了将值设置为null works或-=works的帖子。这两项工作都不做……至少在3.5中是这样。经过进一步的测试,似乎支票只是被缓存了。验证证书后重新检查一次不会导致调用回调。在开发我创建的诊断工具期间,我遇到了类似的问题。我创建了一个windows服务,它向URL列表发出请求。对于每个url,我通过设置以下内容发出一个未经证书验证的请求:
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
然后,使用相同的url,我还尝试通过将属性重置回null来发出带有证书验证的请求,该属性应提供默认功能:
ServicePointManager.ServerCertificateValidationCallback = null;
这产生了意外的结果,因为我的请求仍然在没有证书验证的情况下发出,好像重置被忽略了一样。调试后,我发现如果设置后等待足够长的时间
ServicePointManager.ServerCertificateValidationCallback = null;
然后它实际上被重置,我的请求是用默认证书验证发出的。因此,我只是在提出请求之前先睡30秒:
ServicePointManager.ServerCertificateValidationCallback = null;
System.Threading.Thread.Sleep(30000);
//Make request here
我不明白为什么这样做有效,但确实有效,我相信有更好的方法,如果你知道如何做,请告诉我。我遇到了类似的问题。您可以将ServicePointManager.MaxServicePointIdleTime更改为较低的值,而不是在@Acode Monkey solution上调用Thread.Sleep()
ServicePointManager.MaxServicePointIdleTime = 1;
将回调设置为null可以,但已建立的连接仍在使用中。所以,正如@Acode Monkey所说的,他们的证书在大约30秒内不会被检查 有一种方法可以告诉你,连接不应该使用这么长时间——正如@Kyibe answer中所述。但对我来说,它在100%的情况下不起作用 所以我写了一个小助手,他为我做了这一切:
internal static class ServiceHelper
{
/// <summary>
/// Gets or sets whether to ignore certificate errors.
/// </summary>
public static bool IgnoreCertificateErrors
{
get => _ignoreCertificateErrors;
set => _ignoreCertificateErrors = value;
}
/// <summary>
/// Gets or sets whether to ignore certificate errors.
/// This property is static because it controls the ServicePointManager settings, and that is static.
/// </summary>
private static volatile bool _ignoreCertificateErrors = true;
/// <summary>
/// Callback for certificate validation event, which based on <see cref="_ignoreCertificateErrors"/> will let invalid certificates pass or not.
/// </summary>
private static bool ValidateCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslpolicyerrors)
{
if (_ignoreCertificateErrors)
return true;
// default behavior
return sslpolicyerrors == SslPolicyErrors.None;
}
/// <summary>
/// Calling this method will ensure that certificate validation will be covered by <see cref="IgnoreCertificateErrors" /> property.
/// </summary>
public static void EnsureCustomCertificateValidation()
{
var callbackCount = ServicePointManager.ServerCertificateValidationCallback?.GetInvocationList().Length ?? 0;
// adding callback only if there is no callback already
if (callbackCount == 0)
{
// due to this setting will connection stay active no longer than 1s (so method ValidateCertificate will be called for every action if they are at least 1 second split)
ServicePointManager.MaxServicePointIdleTime = 1000; //ms
// setting the certificate validaction callback
ServicePointManager.ServerCertificateValidationCallback += ValidateCertificate;
}
}
}
内部静态类ServiceHelper
{
///
///获取或设置是否忽略证书错误。
///
公共静态bool IgnoreCertificateErrors
{
get=>\u忽略认证错误;
set=>\u ignoreCertificateErrors=值;
}
///
///获取或设置是否忽略证书错误。
///此属性是静态的,因为它控制ServicePointManager设置,而这是静态的。
///
私有静态易失性bool\u ignoreCertificateErrors=true;
///
///证书验证事件的回调,基于该事件将允许无效证书通过或不通过。
///
私有静态bool ValidateCertificate(对象发送方、X509Certificate证书、X509Chain链、SslPolicyErrors SslPolicyErrors)
{
如果(_ignoreCertificateErrors)
返回true;
//默认行为
返回sslpolicyerrors==sslpolicyerrors.None;
}
///
///调用此方法将确保属性覆盖证书验证。
///
公共静态无效导致重新注册证书评估()
{
var callbackCount=ServicePointManager.ServerCertificateValidationCallback?.GetInvocationList()。长度为0;
//仅在没有回调的情况下添加回调
if(callbackCount==0)
{
//由于此设置,连接将保持活动状态不超过1秒(因此,如果每个操作至少间隔1秒,则将为每个操作调用方法ValidateCertificate)
ServicePointManager.MaxServicePointIdleTime=1000;//毫秒
//设置证书有效性回调
ServicePointManager.ServerCertificateValidationCallback+=ValidateCertificate;
}
}
}
然后在使用任何Web服务或任何其他服务之前,只需调用ServiceHelper.EnsureCustomCertificateValidation()
。
然后,您可以轻松地在忽略证书错误和默认行为之间切换我不同意这一点。我只是用好的和坏的HTTPS URL测试了各种方法。通过将其设置回null,它看起来像回到默认行为。使用相同的解决方案。我以前使用委托将其禁用,然后在finally.works中使用try/catch/finally将其设置为null。使用各种情况(好的和坏的https URL)进行测试。