web-dev-qa-db-fra.com

Comment ignorer la vérification du certificat quand ssl

J'essaie de trouver un moyen d'ignorer la vérification du certificat lorsque vous demandez une ressource Https. Jusqu'à présent, j'ai trouvé un article utile sur Internet. 

Mais j'ai encore un problème. S'il vous plaît examiner mon code. Je ne comprends tout simplement pas ce que signifie le code ServicePointManager.ServerCertificateValidationCallback.

Quand cette méthode déléguée sera-t-elle appelée? Et encore une question, à quel endroit devrais-je écrire ce code? Avant ServicePointManager.ServerCertificateValidationCallback exécuter ou avant 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

Puisqu'il n'y a qu'un seul global ServicePointManager , définir ServicePointManager.ServerCertificateValidationCallback donnera le résultat selon lequel toutes les demandes suivantes hériteront de cette stratégie. Comme il s'agit d'un "paramètre" global, il serait préférable de le définir dans la méthode Application_Start de Global.asax .

La définition du rappel annule le comportement par défaut et vous pouvez créer vous-même une routine de validation personnalisée. 

62
Sani Singh Huttunen

Pour toute personne intéressée à appliquer cette solution au cas par cas, il s'agit d'une option utilisant une expression Lambda. La même expression Lambda peut également être appliquée au filtre global mentionné par blak3r. Cette méthode semble nécessiter .NET 4.5.

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

Dans .NET 4.0, l'expression Lambda peut être appliquée au filtre global en tant que telle

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

Cela a fonctionné pour moi:

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
    };

Extrait d'ici: http://www.west-wind.com/weblog/posts/2011/Feb/11/HttpWebRequest-and-Ignoring-SSL-Certificate-Errors

48
blak3r

Il y a aussi la solution de délégué courte:

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

Il a été mentionné qu'avant .NET 4.5, la propriété de la demande d'accès à sa ServicePointManager n'était pas disponible.

Voici le code .NET 4.0 qui vous donnera accès à ServicePoint au cas par cas. Cela ne vous donne pas accès au rappel sur demande, mais devrait vous permettre de trouver plus de détails sur le problème. Accédez simplement aux propriétés scvPoint.Certificate (ou ClientCertificate si vous préférez).

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

Incidemment, c’est le moyen le moins explicite de désactiver la validation des certificats dans une application donnée que je connais:

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

Basé sur la réponse d'Adam et le commentaire de Rob, j'ai utilisé ceci:

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

qui filtre le "ignorer" un peu. Bien sûr, d’autres émetteurs peuvent être ajoutés… .. Cela a été testé dans .NET 2.0 car nous devons prendre en charge certains codes hérités.

2
Andrej

Exprimé explicitement ...

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

CA5386: Les outils d’analyse de vulnérabilité vous avertissent de ces codes.

Code correct:

ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) =>
{
   return (sslPolicyErrors & SslPolicyErrors.RemoteCertificateNotAvailable) != SslPolicyErrors.RemoteCertificateNotAvailable;
};
0
dev_O

Plutôt que d'ajouter un rappel à ServicePointManager qui remplacera globalement la validation de certificat, vous pouvez définir le rappel sur une instance locale de HttpClient. Cette approche ne devrait affecter que les appels effectués à l'aide de cette instance de HttpClient.

Voici un exemple de code montrant comment ignorer les erreurs de validation de certificat pour des serveurs spécifiques peut être implémenté dans un contrôleur API Web.

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

Astuce: Vous pouvez également utiliser cette méthode pour suivre les certificats qui vont bientôt expirer. Cela peut économiser votre bacon si vous découvrez un certificat sur le point d'expirer et que vous pouvez le réparer à temps. Bon également pour les sociétés tierces - pour nous, il s’agit de DHL/FedEx. DHL vient de laisser expirer un certificat qui nous fait foutre en l'air 3 jours avant Thanksgiving. Heureusement, je suis là pour le réparer ... cette fois!

    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

Plusieurs réponses ci-dessus fonctionnent. Je voulais une approche qui ne nécessite pas de modifications de code ni de sécurité. J'ai donc créé une liste blanche. La liste blanche peut être gérée dans n'importe quel magasin de données. J'ai utilisé le fichier de configuration car c'est une très petite liste.

Mon code est ci-dessous.

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

En ajoutant aux réponses de Sani et de blak3r, j'ai ajouté ce qui suit au code de démarrage de mon application, mais en VB

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

Semble faire l'affaire.

0
MCattle