恢复SSL证书覆盖检查

时间:2010-08-10 01:05:04

标签: c#

我正在编写测试以测试我正在部署的服务,绕过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帮助说ServicePointManager.SecurityProtocol的默认值为null(http://msdn.microsoft.com/en-us/library/system.net.servicepointmanager.securityprotocol.aspx)。将它设置为null会切换到默认的ssl验证,还有其他方法可以做到这一点。

5 个答案:

答案 0 :(得分:6)

在开发我创建的诊断工具期间,我遇到了类似的问题。我创建了一个Windows服务,它向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

我不明白为什么会这样,但确实有更好的方法,如果你知道怎么做,请告诉我。

答案 1 :(得分:2)

我最终将ServicePointManager.SecurityProtocol设置为null,它工作正常。虽然我仍然愿意接受更好的方法来做到这一点


public static void SSLValidationRestore()
        {
            ServicePointManager.ServerCertificateValidationCallback = null;
        }

答案 2 :(得分:2)

将回调设置为null不起作用。相反,所有证书都通过。我不明白为什么这么多人发布了将值设置为null works或 - = works。这项工作也没有......至少在3.5。经过进一步测试后,似乎只是缓存了支票。证书验证一次后重新检查不会导致回调被调用。

答案 3 :(得分:1)

我遇到了类似的问题。您可以将ServicePointManager.MaxServicePointIdleTime更改为较低的值,而不是在@Acode Monkey解决方案上调用Thread.Sleep()。

http://codepen.io/ajkochanowicz/pen/KHdih

答案 4 :(得分:0)

将回调设置为null可以,但是已经建立的连接仍在使用。因此,按照@Acode Monkey的说明,大约30秒内不会检查它们的证书。

有一种方法可以告诉用户不要使用连接太长时间-如@Kyibe答案中所述。但是对我来说,它不适用于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;
        }
    }
}

然后在使用任何WebService或任何其他方法之前,只需调用ServiceHelper.EnsureCustomCertificateValidation()。 然后,您可以轻松地在忽略证书错误和默认行为之间切换