web-dev-qa-db-fra.com

Comment résoudre l'erreur javax.net.ssl.SSLHandshakeException

Je me suis connecté avec VPN pour configurer l’API d’inventaire afin d’obtenir la liste des produits et cela fonctionne bien. Une fois que je reçois le résultat du service Web et que je me lie à l'interface utilisateur. Et aussi j’ai intégré Paypal à mon application pour effectuer un paiement express lorsque je passe un appel de paiement et que j’ai fait face à cette erreur. J'utilise servlet pour les processus back-end. Quelqu'un peut-il dire comment résoudre ce problème?

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

Premièrement, vous devez obtenir le certificat public du serveur auquel vous essayez de vous connecter. Cela peut être fait de différentes manières, par exemple contacter l’administrateur du serveur et le demander, télécharger OpenSSL , ou, puisque cela semble être un serveur HTTP, le connecter à n’importe quel navigateur, visualiser les informations de sécurité de la page et enregistrer une copie du certificat. (Google devrait pouvoir vous dire exactement quoi faire pour votre navigateur spécifique.)

Maintenant que le certificat est enregistré dans un fichier, vous devez l'ajouter à la réserve de confiance de votre JVM. À $Java_HOME/jre/lib/security/ pour les JRE ou $Java_HOME/lib/security pour les JDK, il existe un fichier nommé cacerts, fourni avec Java et contenant les certificats publics des autorités de certification reconnues. Pour importer le nouveau certificat, exécutez keytool en tant qu'utilisateur autorisé à écrire dans cacerts:

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

Il vous demandera probablement un mot de passe. Le mot de passe par défaut fourni avec Java est changeit. Presque personne ne le change. Une fois que vous aurez terminé ces étapes relativement simples, vous communiquerez de manière sécurisée et aurez l’assurance que vous parlez au bon serveur et uniquement au bon serveur (tant qu’ils ne perdent pas leur clé privée).

124
Ryan Stewart

Maintenant, j'ai résolu ce problème de cette façon,

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

Bien entendu, cette solution ne doit être utilisée que dans des scénarios où il n'est pas possible d'installer les certificats requis à l'aide de keytool p. Ex. test local avec certifques temporaires.

12
selladurai

Chaque fois que nous essayons de nous connecter à une URL, 

si le serveur de l'autre site fonctionne sur le protocole https et impose que nous devions communiquer via les informations fournies dans le certificat, puis nous avons l'option suivante:

1) demander le certificat (télécharger le certificat), importer ce certificat dans trustore. Les utilisations Java du trustore par défaut peuvent être trouvées dans\Java\jdk1.6.0_29\jre\lib\security\cacerts, puis, si nous essayons de nous connecter à l'URL, la connexion sera acceptée.

2) Dans les cas commerciaux normaux, nous pouvons nous connecter à des URL internes dans des organisations et nous savons qu'elles sont correctes . Dans de tels cas, vous avez la certitude que c'est l'URL correcte. Dans de tels cas, le code ci-dessus peut être utilisé, ce qui n'exige pas de stocker le certificat pour se connecter à une URL particulière.

pour le point n ° 2, nous devons suivre les étapes ci-dessous:

1) écrivez en dessous de la méthode qui définit HostnameVerifier pour HttpsURLConnection, qui renvoie true pour tous les cas, ce qui signifie que nous faisons confiance au 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) écrivez en dessous de la méthode, qui appelle doTrustToCertificates avant de tenter de se connecter à une 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());
   }

Cet appel renverra le code de réponse = 200 signifie que la connexion est établie.

Pour plus de détails et des exemples, vous pouvez vous référer à URL .

9
Shirishkumar Bari

Je pense que vous essayez de vous connecter à quelque chose en utilisant SSL mais que quelque chose fournit un certificat qui n'est pas vérifié par les autorités de certification racine telles que verisign .. En substance, par défaut, des connexions sécurisées ne peuvent être établies que si la personne qui tente de se connecter sait les clés des contreparties ou un autre verndor tel que verisign peuvent intervenir et dire que la clé publique fournie est bien exacte.

TOUS les OS font confiance à une poignée d'autorités de certification et de petits émetteurs de certificats doivent être certifiés par l'un des grands certificateurs qui forment une chaîne de certificateurs si vous comprenez ce que je veux dire ...

Quoi qu’il en soit, j’ai eu un problème similaire lors de la programmation d’une applet Java et d’un serveur Java (un jour, j’espère écrire un article de blog complet expliquant comment la sécurité a fonctionné :)) 

Essentiellement, je devais extraire les clés publiques du serveur et les stocker dans un magasin de clés à l'intérieur de mon applet. Lorsque je me connectais au serveur, j'utilisais ce magasin de clés pour créer une fabrique de relations de confiance et cette fabrique de clés pour créer le fichier SSL. lien. Il existe également d'autres procédures, telles que l'ajout de la clé à l'hôte approuvé de la machine virtuelle Java et la modification du magasin de clés par défaut au démarrage. 

Je l’ai fait il ya environ deux mois et je n’ai pas de code source sur moi en ce moment .. utilisez google et vous devriez être capable de résoudre ce problème. Si vous ne pouvez pas me renvoyer un message et que je peux vous fournir le code source approprié pour le projet .. Ne savez pas si cela résout votre problème, car vous n'avez pas fourni le code qui cause ces exceptions. De plus, je travaillais avec des applets qui pensaient que je ne comprenais pas pourquoi cela ne fonctionnerait pas sur les Serverlets ...

P.S Je ne peux pas obtenir le code source avant le week-end car SSH externe est désactivé dans mon bureau :(

0
Osama Javed

SSLHandshakeException peut être résolu de deux manières.

  1. Incorporer SSL 

    • Obtenez le SSL (en demandant à l'administrateur du système source, vous pouvez également be télécharger par la commande openssl, ou les navigateurs téléchargent les certificats )

    • Ajoutez le certificat dans le magasin de clés de confiance (cacerts) situé à l'adresse JRE/lib/security 

    • indiquez l'emplacement du fichier de clés certifiées dans les arguments de vm sous la forme "- Djavax.net.ssl.trustStore ="

  2. Ignorer SSL

    Pour ce numéro 2, veuillez consulter mon autre réponse sur un autre site Web stackoverflow: Comment utiliser la vérification SSLIgnorer les erreurs de certificat SSL avec Java

0
Amit Kaneria