Подтвердить что ты не робот

Как вернуть свойство ServerCertificateValidationCallback к по умолчанию?

Я использую следующую строку кода в рамках одного метода, чтобы явно проверять и доверять сертификату SSL со следующего узла: MyTrustedCompany.com:

ServicePointManager.ServerCertificateValidationCallback = Function(obj As [Object], certificate As X509Certificate, chain As X509Chain, errors As SslPolicyErrors) (certificate.Subject.Contains("CN=MyTrustedCompany.com"))

Нет проблем с кодом → работает отлично на 100%.

Проблема в том, что она слишком далеко продвинулась. Я думал, что его область охвата будет только в методе, который я дал ей, но, по-видимому, это свойство Shared в объекте ServicePointManager, и оно должно сохраняться для всего приложения, которое мне не нужно.

Проблема заключается в том, что позже я вызываю веб-сервисы и т.д. и получаю исключение "Не могу установить доверительные отношения...". Это связано с тем, что в строке кода выше я проверяю имя хоста SSL-сертификата specefic на этот метод. Я быстро протестировал Returning "True" из обратного вызова, чтобы всем сертификатам было доверено вместо проверки имени specefic (т.е. MyTrustedCompany) и запросов на подписку . Вот как я знаю, что это назначение обратного вызова доходит до отца, чем этот единственный метод. Конечно, я мог бы расширить обратный вызов, чтобы включить все другие имена сертификатов, но то, что я бы предпочел, это установить "ServerCertificateValidationCallback" обратно на свое поведение по умолчанию. Как и псевдо-код ниже:

ServicePointManager.ServerCertificateValidationCallback = Nothing  'Default checking behavior

Как удалить пользовательскую проверку и вернуть ее по умолчанию? Спасибо!

4b9b3361

Ответ 1

Фактически это работает (так просто, как есть) и заставляет объект вести себя по-умолчанию.

ServicePointManager.ServerCertificateValidationCallback = Nothing

Ответ 2

Вам нужно будет возвращать true только для определенных URL-адресов, но в остальном это делает то, что вы хотите, оставляя возможность использовать несколько делегатов. Логика для каждого обратного вызова может включать проверку через отражение, так что обратный вызов возвращает true только при вызове с определенных компонентов, создавая таким образом туннель между определенными URL-адресами и некоторыми приложениями.

Один из способов использования этого кода: 1. Определите делегат mIgnoreBadCertificates на ранней стадии жизни объекта 2. Задайте свойство, содержащее код "beSecure" true 3. Отправьте запрос Http. 4. Установите свойство false. Это очень важно и должно быть реализовано таким образом, чтобы гарантировать, что он будет вызван. Шаблон IDisposable является одним из вариантов.

 private System.Net.Security.RemoteCertificateValidationCallback mIgnoreBadCertificates = new
    System.Net.Security.RemoteCertificateValidationCallback(
      delegate { return true; });

if (beSecure)
    {   //require secure communications
        System.Net.ServicePointManager.ServerCertificateValidationCallback -= mIgnoreBadCertificates;
        Iwds.EventLogger.LogVeryFrequentEvent("Requiring Good Certificates from Remote Sites");
    }
    else
    {   /// Allow connections to SSL sites that have unsafe certificates.
        System.Net.ServicePointManager.ServerCertificateValidationCallback += mIgnoreBadCertificates;
        Iwds.EventLogger.LogVeryFrequentEvent("Ignoring Bad Certificates from Remote Sites");
    }

Ответ 3

Ключевым моментом в решении вашей проблемы является тот факт, что параметр sender для RemoteCertificateValidationCallback - это WebRequest. Вы можете проверить отправителя на ваш веб-запрос, чтобы вы только проверяли ваш веб-запрос. Вот мое (относительно непроверенное) решение:

// Main Code

request = (FtpWebRequest)FtpWebRequest.Create("ftp://example.com");

using(var validator = new WebRequestCertificateValidator(request))
{
    // etc...
}

// WebRequestCertificateValidator Class

public sealed class WebRequestCertificateValidator : IDisposable
{
    private bool disposed;

    private WebRequest request;

    private RemoteCertificateValidationCallback callback;

    /// <summary>
    /// Creates a certificate validator that allows all certificates for the supplied web request.
    /// </summary>
    /// <param name="request">The WebRequest to validate for.</param>
    public WebRequestCertificateValidator(WebRequest request) : this(request, null)
    {
        //
    }

    /// <summary>
    /// Creates a certificate validator that only allows certificates for the supplied web request of the callback returns true.
    /// </summary>
    /// <param name="request">The WebRequest to validate for.</param>
    /// <param name="callback">The delegate that will be called to validate certificates for the WebRequest.</param>
    public WebRequestCertificateValidator(WebRequest request, RemoteCertificateValidationCallback callback)
    {
        this.disposed = false;

        this.request = request;

        this.callback = callback;

        ServicePointManager.ServerCertificateValidationCallback += this.InternalCallback;
    }

    private bool InternalCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
    {
        WebRequest request = sender as WebRequest;

        if(request != null)
        {
            if(request == this.request)
            {
                if(this.callback != null)
                {
                    return this.callback(sender, certificate, chain, sslPolicyErrors);
                }
            }
        }

        return true;
    }

    public void Dispose()
    {
        if(!this.disposed)
        {
            ServicePointManager.ServerCertificateValidationCallback -= this.InternalCallback;

            this.callback = null;

            this.request = null;

            this.disposed = true;
        }
    }
}

Ответ 4

public class OAuthRequestHandler : WebRequestHandler
{
    public OAuthRequestHandler() : base()
    {
        base.ServerCertificateValidationCallback  += this.InternalCallback;
    }

    private bool InternalCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
    {
        return certificate.Subject.Contains("CN=MyTrustedCompany.com");
    }
}

и в моем запросе командной строки program.cs:

HttpClient client = new HttpClient(new OAuthRequestHandler());
responseString = await client.GetStringAsync("https://localhost:2345");

Можно выполнить больше с параметрами сертификата и отправителя, но ОП запросил выше.