it-swarm-eu.dev

Come risolvere l'errore javax.net.ssl.SSLHandshakeException?

Mi sono connesso con VPN per configurare l'API di inventario per ottenere l'elenco dei prodotti e funziona correttamente. Una volta ottenuto il risultato dal servizio web e leggo all'interfaccia utente. E ho anche integrato Paypal con la mia domanda per effettuare il checkout Express quando faccio una chiamata per il pagamento, sto affrontando questo errore. Io uso servlet per il processo di back-end. Qualcuno può dire come risolvere questo problema?

javax.net.ssl.SSLHandshakeException: Sun.security.validator.ValidatorException: 
PKIX path building failed: Sun.security.provider.certpath.SunCertPathBuilderException:
unable to find valid certification path to requested target
83
selladurai

Innanzitutto, è necessario ottenere il certificato pubblico dal server al quale si sta tentando di connettersi. Ciò può essere fatto in vari modi, come contattare l'amministratore del server e chiederlo, utilizzare OpenSSL per scaricarlo , oppure, poiché questo sembra essere un server HTTP, collegarsi ad esso con qualsiasi browser, visualizzando le informazioni sulla sicurezza della pagina e il salvataggio di una copia del certificato. (Google dovrebbe essere in grado di dirti esattamente cosa fare per il tuo browser specifico.)

Ora che il certificato è stato salvato in un file, è necessario aggiungerlo all'archivio fidato di JVM. A $Java_HOME/jre/lib/security/ per JREs o $Java_HOME/lib/security per JDKs, c'è un file chiamato cacerts, che viene fornito con Java e contiene i certificati pubblici delle ben note autorità di certificazione. Per importare il nuovo certificato, esegui keytool come utente che ha il permesso di scrivere in cacerts:

keytool -import -file <the cert file> -alias <some meaningful name> -keystore <path to cacerts file>

Molto probabilmente ti chiederà una password. La password predefinita fornita con Java è changeit. Quasi nessuno lo cambia. Dopo aver completato questi passaggi relativamente semplici, comunicherai in modo sicuro e con la certezza che stai parlando con il server giusto e solo con il server giusto (a patto che non perdano la chiave privata).

124
Ryan Stewart

Ora ho risolto questo problema in questo modo,

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import Java.io.OutputStream; 

// Create a trust manager that does not validate certificate chains like the default 

TrustManager[] trustAllCerts = new TrustManager[]{
        new X509TrustManager() {

            public Java.security.cert.X509Certificate[] getAcceptedIssuers()
            {
                return null;
            }
            public void checkClientTrusted(Java.security.cert.X509Certificate[] certs, String authType)
            {
                //No need to implement.
            }
            public void checkServerTrusted(Java.security.cert.X509Certificate[] certs, String authType)
            {
                //No need to implement.
            }
        }
};

// Install the all-trusting trust manager
try 
{
    SSLContext sc = SSLContext.getInstance("SSL");
    sc.init(null, trustAllCerts, new Java.security.SecureRandom());
    HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
} 
catch (Exception e) 
{
    System.out.println(e);
}

Ovviamente questa soluzione dovrebbe essere utilizzata solo in scenari, dove non è possibile installare i certificati richiesti utilizzando keytool e.g. test locali con certificati temporanei.

12
selladurai

Ogni volta che stiamo cercando di connetterci all'URL, 

se il server dell'altro sito è in esecuzione su protocollo https e sta richiedendo che dovremmo comunicare tramite le informazioni fornite nel certificato allora abbiamo la seguente opzione:

1) richiedi il certificato (scarica il certificato), importa questo certificato in trust. Default trustore Gli usi Java possono essere trovati in\Java\jdk1.6.0_29\jre\lib\security\cacerts, quindi se dovessimo riprovare a connetterci alla connessione URL verrebbero accettati.

2) In normali casi aziendali, potremmo collegarci a URL interni nelle organizzazioni e sappiamo che sono corretti . In questi casi, si ha fiducia che sia l'URL corretto. In questi casi, sopra, è possibile utilizzare il codice che non impone di archiviare il certificato per connettersi a un particolare URL.

per il punto n. 2 dobbiamo seguire i seguenti passaggi:

1) scrivi sotto il metodo che imposta HostnameVerifier per HttpsURLConnection che restituisce true per tutti i casi, il che significa che stiamo attendendo il trustStore.

  // trusting all certificate 
 public void doTrustToCertificates() throws Exception {
        Security.addProvider(new com.Sun.net.ssl.internal.ssl.Provider());
        TrustManager[] trustAllCerts = new TrustManager[]{
                new X509TrustManager() {
                    public X509Certificate[] getAcceptedIssuers() {
                        return null;
                    }

                    public void checkServerTrusted(X509Certificate[] certs, String authType) throws CertificateException {
                        return;
                    }

                    public void checkClientTrusted(X509Certificate[] certs, String authType) throws CertificateException {
                        return;
                    }
                }
        };

        SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, trustAllCerts, new SecureRandom());
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
        HostnameVerifier hv = new HostnameVerifier() {
            public boolean verify(String urlHostName, SSLSession session) {
                if (!urlHostName.equalsIgnoreCase(session.getPeerHost())) {
                    System.out.println("Warning: URL Host '" + urlHostName + "' is different to SSLSession Host '" + session.getPeerHost() + "'.");
                }
                return true;
            }
        };
        HttpsURLConnection.setDefaultHostnameVerifier(hv);
    }

2) scrivi sotto metodo, che chiama doTrustToCertificates prima di provare a connettersi all'URL

    // connecting to URL
    public void connectToUrl(){
     doTrustToCertificates();//  
     URL url = new URL("https://www.example.com");
     HttpURLConnection conn = (HttpURLConnection)url.openConnection(); 
     System.out.println("ResponseCode ="+conn.getResponseCode());
   }

Questa chiamata restituirà il codice di risposta = 200 significa che la connessione ha avuto successo.

Per maggiori dettagli ed esempi di esempio puoi fare riferimento a URL .

9

Credo che tu stia cercando di connettersi a qualcosa usando SSL ma che qualcosa sta fornendo un certificato che non è verificato dalle autorità di certificazione di root come verisign .. In sostanza, per impostazione predefinita le connessioni sicure possono essere stabilite solo se la persona che sta tentando di connettersi sa le chiavi della controparte o qualche altro verndor come verisign possono intervenire e dire che la chiave pubblica fornita è davvero giusta.

TUTTI i sistemi operativi si fidano di una manciata di autorità di certificazione e di emittenti di certificati minori che devono essere certificati da uno dei grandi certificatori che fanno una catena di certificatori se si ottiene ciò che intendo ...

Comunque, tornando al punto .. Ho avuto un problema simile durante la programmazione di un applet Java e un server Java (speriamo che un giorno scriverò un post completo su come ho ottenuto tutta la sicurezza per funzionare :)) 

In pratica, quello che dovevo fare era estrarre le chiavi pubbliche dal server e archiviarle in un keystore all'interno della mia applet e quando mi sono collegato al server ho usato questo keystore per creare un trust factory e quel trust factory per creare lo ssl connessione. Esistono anche procedure di modifica, come l'aggiunta della chiave all'host attendibile di JVM e la modifica dell'archivio di fiducia predefinito all'avvio. 

L'ho fatto circa due mesi fa e non ho il codice sorgente su di me in questo momento .. usa google e dovresti essere in grado di risolvere questo problema. Se non riesci a contattarmi e posso fornirti il ​​codice sorgente pertinente per il progetto. Non so se questo risolve il tuo problema poiché non hai fornito il codice che causa queste eccezioni. Inoltre stavo lavorando con applet pensando che non capisco perché non funzionerà su Serverlet ...

P.S Non riesco ad ottenere il codice sorgente prima del fine settimana poiché SSH esterno è disabilitato nel mio ufficio :(

0
Osama Javed

SSLHandshakeException può essere risolto in 2 modi.

  1. Incorporando SSL 

    • Ottieni l'SSL (chiedendo all'amministratore del sistema di origine, può ancheessere scaricato dal comando openssl, o qualsiasi browser scarica i certificati )

    • Aggiungere il certificato al truststore (cacerts) situato in JRE/lib/security 

    • fornire il percorso truststore negli argomenti vm come "- Djavax.net.ssl.trustStore ="

  2. Ignorando SSL

    Per questo n. 2, visita la mia altra risposta su un altro sito Web StackOverflow: Come eseguire la verifica SSLIgnora gli errori del certificato SSL con Java

0
Amit Kaneria