44 votes

Connexion URL Java et HTTPS sans téléchargement de certificat

Ce code se connecte à un site HTTPS et je suppose que je ne vérifie pas le certificat. Mais pourquoi ne dois-je pas installer un certificat localement pour le site? Ne devrais-je pas avoir à installer un certificat localement et à le charger pour ce programme ou est-il téléchargé derrière les couvertures? Le trafic entre le client et le site distant est-il toujours chiffré en cours de transmission?

 import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import java.net.URLConnection;
import java.security.cert.X509Certificate;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

public class TestSSL {

    public static void main(String[] args) throws Exception {
        // Create a trust manager that does not validate certificate chains
        TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                return null;
            }
            public void checkClientTrusted(X509Certificate[] certs, String authType) {
            }
            public void checkServerTrusted(X509Certificate[] certs, String authType) {
            }
        } };
        // Install the all-trusting trust manager
        final SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, trustAllCerts, new java.security.SecureRandom());
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
        // Create all-trusting host name verifier
        HostnameVerifier allHostsValid = new HostnameVerifier() {
            public boolean verify(String hostname, SSLSession session) {
                return true;
            }
        };

        // Install the all-trusting host verifier
        HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);

        URL url = new URL("https://www.google.com");
        URLConnection con = url.openConnection();
        final Reader reader = new InputStreamReader(con.getInputStream());
        final BufferedReader br = new BufferedReader(reader);        
        String line = "";
        while ((line = br.readLine()) != null) {
            System.out.println(line);
        }        
        br.close();
    } // End of main 
} // End of the class //
 

31voto

Bruno Points 47560

La raison pour laquelle vous n'avez pas à charger un certificat locales est que vous avez explicitement choisi de ne pas vérifier le certificat, avec cette confiance gestionnaire de fiducies de tous les certificats.

Le trafic sera encore chiffré, mais vous êtes à l'ouverture de la connexion à Man-In-The-Middle attaques: vous êtes à communiquer secrètement avec quelqu'un, vous êtes tout simplement pas sûr de savoir si c'est le serveur auquel vous vous attendez, ou d'un éventuel attaquant.

Si votre certificat de serveur vient d'un bien-connu CA, une partie de la valeur par défaut faisceau de certificats d'autorité de certification fourni avec le JRE (habituellement cacerts le fichier, voir JSSE guide de Référence), vous pouvez simplement utiliser la valeur par défaut de confiance manager, vous n'avez pas à définir quoi que ce soit ici.

Si vous avez un certificat spécifique (auto-signé ou à partir de votre propre autorité de certification), vous pouvez utiliser la valeur par défaut de confiance gestionnaire ou peut-être initialisée avec un truststore, mais vous devez importer le certificat explicitement dans votre magasin de confiance (après vérification indépendante), comme décrit dans cette réponse. Vous pourriez également être intéressé par cette réponse.

12voto

Stephen C Points 255558

Mais pourquoi n'ai-je pas installer un certificat localement pour le site?

Bien le code que vous utilisez est explicitement conçu pour accepter le certificat, sans aucun contrôle. Ce n'est pas bien pratique ... mais si c'est ce que vous voulez faire, alors (évidemment), il n'est pas nécessaire d'installer un certificat que votre code est explicitement ignorant.

Je ne devrais pas avoir à installer un certificat localement et de les charger de ce programme ou est-il téléchargé derrière le couvre?

Non, et non. Voir ci-dessus.

Le trafic entre le client sur le site distant, toujours crypté dans la transmission?

Oui, il est. Cependant, le problème est que depuis que vous lui avez dit de faire confiance au certificat du serveur sans faire toutes les vérifications, vous ne savez pas si vous parlez au serveur réel, ou à quelque autre site qui est en prétendant être le vrai serveur. Si c'est un problème dépend des circonstances.


Si nous avons utilisé le navigateur comme un exemple, typiquement un navigateur ne peut pas demander à l'utilisateur de manière explicite, installer un certificat ssl du site visité.

Le navigateur dispose d'un ensemble de certificats racine de confiance pré-installé. La plupart du temps, lorsque vous visitez un "https" sur le site, le navigateur peut vérifier que le certificat du site est (en fin de compte, via la chaîne de certificats), fixée par l'une de ces trusted cert. Si le navigateur ne reconnaît pas le cert au début de la chaîne, comme étant un trusted cert (ou si les certificats ne sont pas à jour ou invalide / inapproprié), alors il affichera un message d'avertissement.

Java fonctionne de la même manière. La JVM du fichier de clés dispose d'un ensemble de certificats approuvés, et le même processus est utilisé pour vérifier le certificat est sécurisé par un certificat de confiance.

Le java client https prise en charge des api d'un certain type de mécanisme pour télécharger le certificat de l'information automatiquement?

Pas de. Permettant d'applications pour télécharger des certificats à partir des endroits aléatoires, et les installer (de confiance) dans le système de fichier de clés serait un trou de sécurité.

1voto

jww Points 9514

Java et HTTPS url de connexion sans téléchargement certificat

Si vous voulez vraiment éviter de télécharger le certificat du serveur, puis utiliser un anonyme, un protocole comme Anonymous, l'échange de clés Diffie-Hellman (ADH). Le certificat du serveur n'est pas envoyé avec l'ADH et amis.

Vous sélectionnez un anonyme, un protocole avec l' setEnabledCipherSuites. Vous pouvez voir la liste des suites de chiffrement disponibles avec getEnabledCipherSuites.

Liés: c'est pourquoi vous appelez SSL_get_peer_certificate dans OpenSSL. Vous recevrez un X509_V_OK avec un anonyme, un protocole, et c'est ainsi que vous vérifiez pour voir si un certificat a été utilisé dans l'échange.

Mais comme Bruno et Stephed C dit, c'est une mauvaise idée pour éviter les chèques ou d'utiliser un anonyme protocole.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X