[c#] Impossibile stabilire una relazione di trust per il canale protetto SSL / TLS: SOAP



6 Answers

I seguenti frammenti risolveranno il caso in cui c'è qualcosa di sbagliato nel certificato SSL sul server che stai chiamando. Ad esempio, potrebbe essere autofirmato o il nome host tra il certificato e il server potrebbe non corrispondere.

Questo è pericoloso se stai chiamando un server al di fuori del tuo controllo diretto, dal momento che non puoi più essere sicuro che stai parlando al server che pensi di essere connesso. Tuttavia, se si ha a che fare con server interni e ottenere un certificato "corretto" non è pratico, utilizzare quanto segue per comunicare al servizio Web di ignorare i problemi del certificato e di attaccare coraggiosamente il soldato.

Le prime due usano espressioni lambda, la terza usa codice normale. Il primo accetta qualsiasi certificato. Gli ultimi due controllano almeno che il nome host nel certificato sia quello che ci si aspetta.
... spero che tu trovi utile

//Trust all certificates
System.Net.ServicePointManager.ServerCertificateValidationCallback =
    ((sender, certificate, chain, sslPolicyErrors) => true);

// trust sender
System.Net.ServicePointManager.ServerCertificateValidationCallback
                = ((sender, cert, chain, errors) => cert.Subject.Contains("YourServerName"));

// validate cert by calling a function
ServicePointManager.ServerCertificateValidationCallback += new RemoteCertificateValidationCallback(ValidateRemoteCertificate);

// callback used to validate the certificate in an SSL conversation
private static bool ValidateRemoteCertificate(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors policyErrors)
{
    bool result = false;
    if (cert.Subject.ToUpper().Contains("YourServerName"))
    {
        result = true;
    }

    return result;
}
Question

Ho una semplice chiamata al servizio web, generata da un'applicazione Windows .NET (C #) 2.0, tramite il proxy del servizio Web generato da Visual Studio, per un servizio Web scritto anche in C # (2.0). Questo ha funzionato per diversi anni, e continua a farlo nella decina di luoghi in cui è in esecuzione.

Una nuova installazione in un nuovo sito è in esecuzione in un problema. Quando si tenta di richiamare il servizio Web, fallisce con il messaggio che dice:

Impossibile stabilire una relazione di trust per il canale protetto SSL / TLS

L'URL del servizio web utilizza SSL (https: //), ma questo ha funzionato da molto tempo (e continua a farlo) da molte altre posizioni.

Dove guardo? Questo potrebbe essere un problema di sicurezza tra Windows e .NET che è unico per questa installazione? In tal caso, dove imposto le relazioni di fiducia? Mi sono perso!




Luca ha scritto un bel articolo su questo ... piuttosto semplice ... provalo

La soluzione di Luke

Motivo (citazione dal suo articolo (meno cursing)) ".. Il problema con il codice sopra riportato è che non funziona se il tuo certificato non è valido. Perché dovrei postare su una pagina web con certificato SSL non valido? Perché Sono a buon mercato e non avevo voglia di pagare Verisign o uno degli altri ** - * s per un certificato alla mia casella di prova, quindi mi sono autofirmato. Quando ho inviato la richiesta ho ricevuto un'eccezionale eccezione a me:

System.Net.WebException La connessione sottostante è stata chiusa. Impossibile stabilire una relazione di trust con il server remoto.

Non so voi, ma per me quell'eccezione sembrava qualcosa che sarebbe stato causato da uno stupido errore nel mio codice che stava causando il fallimento del POST. Così ho continuato a cercare, a modificare e fare ogni genere di cose strane. Solo dopo aver cercato su google cosa ho scoperto che il comportamento predefinito dopo aver incontrato un certificato SSL non valido è di lanciare questa eccezione. .."




Per coloro che stanno avendo questo problema attraverso un lato client VS una volta aggiunto con successo un riferimento al servizio e cercando di eseguire la prima chiamata ha ottenuto questa eccezione: "La connessione sottostante è stata chiusa: Impossibile stabilire la relazione di trust per il canale sicuro SSL / TLS" Se stai usando (come il mio caso) un URL dell'endpoint con l'indirizzo IP e hai ottenuto questa eccezione, quindi dovresti probabilmente aggiungere nuovamente il riferimento al servizio seguendo questi passaggi:

  • Apri l'URL dell'endpoint in Internet Explorer.
  • Fai clic sull'errore del certificato (icona rossa nella barra degli indirizzi)
  • Clicca su Visualizza certificati.
  • Prendi il file "nome" e sostituisci l'indirizzo IP o il nome che stavamo usando e ottenendo l'errore per questo "nome".

Riprova :). Grazie




Se non funziona funziona male, quando ServerCertificateValidationCallback restituisce true; My ServerCertificateValidationCallback code:

ServicePointManager.ServerCertificateValidationCallback += delegate
{
    LogWriter.LogInfo("Проверка сертификата отключена, на уровне ServerCertificateValidationCallback");
    return true;
};

Il mio codice che impedisce l'esecuzione di ServerCertificateValidationCallback:

     if (!(ServicePointManager.CertificatePolicy is CertificateValidation))
    {
        CertificateValidation certValidate = new CertificateValidation();
        certValidate.ValidatingError += new CertificateValidation.ValidateCertificateEventHandler(this.OnValidateCertificateError);
        ServicePointManager.CertificatePolicy = certValidate;
    }

Funzione OnValidateCertificateError:

private void OnValidateCertificateError(object sender, CertificateValidationEventArgs e)
{
    string msg = string.Format(Strings.OnValidateCertificateError, e.Request.RequestUri, e.Certificate.GetName(), e.Problem, new Win32Exception(e.Problem).Message);
    LogWriter.LogError(msg);
    //Message.ShowError(msg);
}

Ho disabilitato il codice CertificateValidation e ServerCertificateValidationCallback in esecuzione molto bene




Ho avuto un problema simile nell'app .NET in Internet Explorer.

Ho risolto il problema aggiungendo il certificato (certificato VeriSign Classe 3 nel mio caso) ai certificati degli editori attendibili.

Vai a Opzioni Internet-> Contenuto -> Editori e importa

Puoi ottenere il certificato se lo esporti da:

Opzioni Internet-> Contenuto -> Certificati -> Autorità di certificazione intermedie -> Autorità di certificazione primaria pubblica di Classe 3 VeriSign - G5




Personalmente mi piace di più la seguente soluzione:

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

... quindi prima di richiedere l'errore, procedi come segue

System.Net.ServicePointManager.ServerCertificateValidationCallback = delegate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { return true; };

Trovato questo dopo aver consultato la soluzione di Luke




Se non vuoi fidarti ciecamente di tutti e fare un'eccezione di fiducia solo per alcuni host, la seguente soluzione è più appropriata.

public static class Ssl
{
    private static readonly string[] TrustedHosts = new[] {
      "host1.domain.com", 
      "host2.domain.com"
    };

    public static void EnableTrustedHosts()
    {
      ServicePointManager.ServerCertificateValidationCallback = 
      (sender, certificate, chain, errors) =>
      {
        if (errors == SslPolicyErrors.None)
        {
          return true;
        }

        var request = sender as HttpWebRequest;
        if (request != null)
        {
          return TrustedHosts.Contains(request.RequestUri.Host);
        }

        return false;
      };
    }
}

Quindi chiama semplicemente Ssl.EnableTrustedHosts all'avvio dell'app.




Related