C# 还原SSL证书覆盖检查

C# 还原SSL证书覆盖检查,c#,C#,我正在编写一个测试来测试我正在部署的服务,为了绕过ssl证书检查,我使用以下代码段实现了ssl覆盖: public static void SSLValidationOverride() { ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(OnValidationCallba

我正在编写一个测试来测试我正在部署的服务,为了绕过ssl证书检查,我使用以下代码段实现了ssl覆盖:


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)进行测试。