it-roy-ru.com

Как игнорировать проверку сертификата при ssl

Я пытаюсь найти способ игнорировать проверку сертификата при запросе ресурса Https, поэтому я нашел несколько полезных статей в Интернете. 

Но у меня все еще есть некоторые проблемы. Пожалуйста, ознакомьтесь с моим кодом. Я просто не понимаю, что означает код ServicePointManager.ServerCertificateValidationCallback.

Когда будет вызван этот метод делегата? И еще один вопрос, в каком месте я должен написать этот код? Перед выполнением ServicePointManager.ServerCertificateValidationCallback или перед Stream stream = request.GetRequestStream()

public HttpWebRequest GetRequest()
{
    CookieContainer cookieContainer = new CookieContainer();

    // Create a request to the server
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(_remoteUrl);

    #region Set request parameters

    request.Method = _context.Request.HttpMethod;
    request.UserAgent = _context.Request.UserAgent;
    request.KeepAlive = true;
    request.CookieContainer = cookieContainer;
    request.PreAuthenticate = true;
    request.AllowAutoRedirect = false;

    #endregion

    // For POST, write the post data extracted from the incoming request
    if (request.Method == "POST")
    {
        Stream clientStream = _context.Request.InputStream;
        request.ContentType = _context.Request.ContentType;
        request.ContentLength = clientStream.Length;

        ServicePointManager.ServerCertificateValidationCallback = delegate(
            Object obj, X509Certificate certificate, X509Chain chain, 
            SslPolicyErrors errors)
            {
                return (true);
            };

            Stream stream = request.GetRequestStream();

            ....
        }

        ....

        return request;
    }
}   
112
Joe.wang

Поскольку существует только один глобальный ServicePointManager , настройка ServicePointManager.ServerCertificateValidationCallback приведет к тому, что все последующие запросы будут наследовать эту политику. Поскольку это глобальная «настройка», было бы предпочтительнее установить ее в Application_Start метод в Global.asax .

Настройка обратного вызова переопределяет поведение по умолчанию, и вы можете сами создать собственную процедуру проверки. 

62
Sani Singh Huttunen

Для тех, кто заинтересован в применении этого решения для каждого запроса, этот вариант является опцией и использует лямбда-выражение. То же самое лямбда-выражение может быть применено и к глобальному фильтру, упомянутому blak3r. Этот метод требует .NET 4.5.

String url = "https://www.stackoverflow.com";
HttpWebRequest request = HttpWebRequest.CreateHttp(url);
request.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true;

В .NET 4.0 лямбда-выражение можно применять к глобальному фильтру как таковому.

ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true;
146
Adam Venezia

Это сработало для меня:

System.Net.ServicePointManager.ServerCertificateValidationCallback +=
delegate(object sender, System.Security.Cryptography.X509Certificates.X509Certificate certificate,
                        System.Security.Cryptography.X509Certificates.X509Chain chain,
                        System.Net.Security.SslPolicyErrors sslPolicyErrors)
    {
        return true; // **** Always accept
    };

Фрагмент отсюда: http://www.west-wind.com/weblog/posts/2011/Feb/11/HttpWebRequest-and-Ignoring-SSL-Certificate-Errors

48
blak3r

Также есть короткое делегатское решение:

ServicePointManager.ServerCertificateValidationCallback = delegate { return true; }; 
19
Andrej Rommel

Было упомянуто, что до .NET 4.5 свойство по запросу на доступ к его ServicePointManager было недоступно.

Вот код .NET 4.0, который даст вам доступ к ServicePoint для каждого запроса. Он не дает вам доступа к обратному вызову для каждого запроса, но должен позволить вам узнать больше о проблеме. Просто откройте свойства scvPoint.Certificate (или ClientCertificate, если хотите).

WebRequest request = WebRequest.Create(uri);

// oddity: these two .Address values are not necessarily the same!
//  The service point appears to be related to the .Host, not the Uri itself.
//  So, check the .Host vlaues before fussing in the debugger.
//
ServicePoint svcPoint = ServicePointManager.FindServicePoint(uri);
if (null != svcPoint)
{
    if (!request.RequestUri.Host.Equals(svcPoint.Address.Host, StringComparison.OrdinalIgnoreCase))
    {
        Debug.WriteLine(".Address              == " + request.RequestUri.ToString());
        Debug.WriteLine(".ServicePoint.Address == " + svcPoint.Address.ToString());
    }
    Debug.WriteLine(".IssuerName           == " + svcPoint.Certificate.GetIssuerName());
}
5
Jesse Chisholm

Кстати, это наименее подробный способ отключения проверки всех сертификатов в данном приложении, о котором я знаю:

ServicePointManager.ServerCertificateValidationCallback = (a, b, c, d) => true;
3
Melbourne Developer

На основании ответа Адама и комментария Роба я использовал это:

ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => certificate.Issuer == "CN=localhost";

который фильтрует «игнорирование» несколько. Другие эмитенты могут быть добавлены по мере необходимости, конечно . Это было протестировано в .NET 2.0, так как нам нужно поддерживать некоторый унаследованный код.

2
Andrej

Выражается явно ...

ServicePointManager.ServerCertificateValidationCallback += new System.Net.Security.RemoteCertificateValidationCallback(CertCheck);

private static bool CertCheck(object sender, X509Certificate cert,
X509Chain chain, System.Net.Security.SslPolicyErrors error)
{
    return true;
}
1
dev_O

Вместо добавления обратного вызова в ServicePointManager, который будет переопределять проверку сертификата глобально, вы можете установить обратный вызов для локального экземпляра HttpClient. Этот подход должен влиять только на вызовы, сделанные с использованием этого экземпляра HttpClient.

Вот пример кода, показывающий, как игнорирование ошибок проверки сертификата для определенных серверов может быть реализовано в контроллере Web API.

using System.Net.Http;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;

public class MyController : ApiController
{

    // use this HttpClient instance when making calls that need cert errors suppressed
    private static readonly HttpClient httpClient;

    static MyController()
    {
        // create a separate handler for use in this controller
        var handler = new HttpClientHandler();

        // add a custom certificate validation callback to the handler
        handler.ServerCertificateCustomValidationCallback = ((sender, cert, chain, errors) => ValidateCert(sender, cert, chain, errors));

        // create an HttpClient that will use the handler
        httpClient = new HttpClient(handler);
    }

    protected static ValidateCert(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors errors)
    {

        // set a list of servers for which cert validation errors will be ignored
        var overrideCerts = new string[]
        {
            "myproblemserver",
            "someotherserver",
            "localhost"
        };

        // if the server is in the override list, then ignore any validation errors
        var serverName = cert.Subject.ToLower();
        if (overrideCerts.Any(overrideName => serverName.Contains(overrideName))) return true;

        // otherwise use the standard validation results
        return errors == SslPolicyErrors.None;
    }

}
0
Sheldon

Совет: Вы также можете использовать этот метод для отслеживания сертификатов, срок действия которых скоро истекает. Это может спасти ваш бекон, если вы обнаружите сертификат, срок годности которого истекает, и сможете исправить его вовремя. Хорошо также для сторонних компаний - для нас это DHL/FedEx. DHL просто дала срок действия сертификата, который портит нам 3 дня до Дня благодарения. К счастью, я рядом, чтобы исправить это ... на этот раз!

    private static DateTime? _nextCertWarning;
    private static bool ValidateRemoteCertificate(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors error)
    {
        if (error == SslPolicyErrors.None)
        {
            var cert2 = cert as X509Certificate2;
            if (cert2 != null)
            { 
                // If cert expires within 2 days send an alert every 2 hours
                if (cert2.NotAfter.AddDays(-2) < DateTime.Now)
                {
                    if (_nextCertWarning == null || _nextCertWarning < DateTime.Now)
                    {
                        _nextCertWarning = DateTime.Now.AddHours(2);

                        ProwlUtil.StepReached("CERT EXPIRING WITHIN 2 DAYS " + cert, cert.GetCertHashString());   // this is my own function
                    }
                }
            }

            return true;
        }
        else
        {
            switch (cert.GetCertHashString())
            {
                // Machine certs - SELF SIGNED
                case "066CF9CAD814DE2097D367F22D3A7E398B87C4D6":    

                    return true;

                default:
                    ProwlUtil.StepReached("UNTRUSTED CERT " + cert, cert.GetCertHashString());
                    return false;
            }
        }
    }
0
Simon_Weaver

Несколько ответов выше работают. Я хотел подход, при котором мне не нужно было постоянно вносить изменения в код, и я не делал свой код небезопасным. Поэтому я создал белый список. Белый список может быть сохранен в любом хранилище данных. Я использовал конфигурационный файл, так как это очень маленький список.

Мой код ниже.

ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, error) => {
    return error == System.Net.Security.SslPolicyErrors.None || certificateWhitelist.Contains(cert.GetCertHashString());
};
0
Osa E

Добавляя ответы Сани и Blak3r, я добавил следующее в код запуска моего приложения, но в VB:

'** Overriding the certificate validation check.
Net.ServicePointManager.ServerCertificateValidationCallback = Function(sender, certificate, chain, sslPolicyErrors) True

Кажется, чтобы сделать трюк.

0
MCattle