web-dev-qa-db-fra.com

Java: fonction prioritaire pour désactiver la vérification du certificat SSL

Le service Web repose sur SSL et il a un certificat auto-signé, hébergé dans un système distant. J'ai déjà créé un client accédant à ce service Web. Cela se fait en ajoutant le certificat au magasin de clés par programme .

Maintenant, j'ai entendu dire qu'il n'est pas nécessaire d'ajouter un certificat au magasin de clés pour accéder à un service Web auto-signé. Au lieu de cela, nous pouvons désactiver la vérification du certificat en remplaçant certaines méthodes. Est-ce vrai? Quelles sont ces méthodes? Aidez-moi.

27
Sumithlal

Cela devrait être suffisant. Je l'utilise lorsque je teste du code par rapport à des serveurs de test et de transfert sur lesquels nous n'avons pas de certificats correctement signés. Cependant, vous devriez vraiment vraiment envisager d'obtenir un certificat SSL valide sur votre serveur de production. Personne ne veut être mis sur écoute et voir sa vie privée violée.

SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, new TrustManager[] { new TrustAllX509TrustManager() }, new Java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
HttpsURLConnection.setDefaultHostnameVerifier( new HostnameVerifier(){
    public boolean verify(String string,SSLSession ssls) {
        return true;
    }
});

Et ça.

import javax.net.ssl.X509TrustManager;
import Java.security.cert.X509Certificate;

/**
 * DO NOT USE IN PRODUCTION!!!!
 * 
 * This class will simply trust everything that comes along.
 * 
 * @author frank
 *
 */
public class TrustAllX509TrustManager implements X509TrustManager {
    public X509Certificate[] getAcceptedIssuers() {
        return new X509Certificate[0];
    }

    public void checkClientTrusted(Java.security.cert.X509Certificate[] certs,
            String authType) {
    }

    public void checkServerTrusted(Java.security.cert.X509Certificate[] certs,
            String authType) {
    }

}

Bonne chance!

=== MISE À JOUR ===

Je voulais juste souligner qu'il existe un service appelé Let's Encrypt qui automatise le processus de génération et de configuration des certificats SSL/TLS reconnus par pratiquement tout le monde, et c'est absolument gratuit!

34
Paaske

Ignorer les certificats par connexion est beaucoup plus sûr car tout autre code utilisera toujours les valeurs par défaut sécurisées.

Le code suivant:

  • Remplace le gestionnaire d'approbation et le vérificateur de nom d'hôte par connexion.
  • Réutilise SSLSocketFactory afin de prendre en charge les connexions persistantes, en contournant la négociation SSL coûteuse pour les demandes répétées au même serveur.

Comme d'autres l'ont déclaré, cela ne devrait être utilisé que pour les tests et/ou pour les systèmes internes communiquant avec d'autres systèmes internes.

import Java.io.BufferedReader;
import Java.io.IOException;
import Java.io.InputStreamReader;
import Java.net.HttpURLConnection;
import Java.net.URL;
import Java.security.KeyManagementException;
import Java.security.NoSuchAlgorithmException;
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.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

public class TestPersistentConnection
{
    private static SSLSocketFactory sslSocketFactory = null;

    /**
     * Use the VM argument <code>-Djavax.net.debug=ssl</code> for SSL specific debugging;
     * the SSL handshake will appear a single time when connections are re-used, and multiple
     * times when they are not.
     * 
     * Use the VM <code>-Djavax.net.debug=all</code> for all network related debugging, but 
     * note that it is verbose.
     * 
     * @throws Exception
     */
    public static void main(String[] args) throws Exception
    {

        //URL url = new URL("https://google.com/");
        URL url = new URL("https://localhost:8443/");

        // Disable first
        request(url, false);

        // Enable; verifies our previous disable isn't still in effect.
        request(url, true);
    }

    public static void request(URL url, boolean enableCertCheck) throws Exception {
        BufferedReader reader = null;
        // Repeat several times to check persistence.
        System.out.println("Cert checking=["+(enableCertCheck?"enabled":"disabled")+"]");
        for (int i = 0; i < 5; ++i) {
            try {

                HttpURLConnection httpConnection = (HttpsURLConnection) url.openConnection();

                // Normally, instanceof would also be used to check the type.
                if( ! enableCertCheck ) {
                    setAcceptAllVerifier((HttpsURLConnection)httpConnection);
                }

                reader = new BufferedReader(new InputStreamReader(httpConnection.getInputStream()), 1);

                char[] buf = new char[1024];
                StringBuilder sb = new StringBuilder();
                int count = 0;
                while( -1 < (count = reader.read(buf)) ) {
                    sb.append(buf, 0, count);
                }
                System.out.println(sb.toString());

                reader.close();

            } catch (IOException ex) {
                System.out.println(ex);

                if( null != reader ) {
                    reader.close();
                }
            }
        }
    }

    /**
     * Overrides the SSL TrustManager and HostnameVerifier to allow
     * all certs and hostnames.
     * WARNING: This should only be used for testing, or in a "safe" (i.e. firewalled)
     * environment.
     * 
     * @throws NoSuchAlgorithmException
     * @throws KeyManagementException
     */
    protected static void setAcceptAllVerifier(HttpsURLConnection connection) throws NoSuchAlgorithmException, KeyManagementException {

        // Create the socket factory.
        // Reusing the same socket factory allows sockets to be
        // reused, supporting persistent connections.
        if( null == sslSocketFactory) {
            SSLContext sc = SSLContext.getInstance("SSL");
            sc.init(null, ALL_TRUSTING_TRUST_MANAGER, new Java.security.SecureRandom());
            sslSocketFactory = sc.getSocketFactory();
        }

        connection.setSSLSocketFactory(sslSocketFactory);

        // Since we may be using a cert with a different name, we need to ignore
        // the hostname as well.
        connection.setHostnameVerifier(ALL_TRUSTING_HOSTNAME_VERIFIER);
    }

    private static final TrustManager[] ALL_TRUSTING_TRUST_MANAGER = new TrustManager[] {
        new X509TrustManager() {
            public X509Certificate[] getAcceptedIssuers() {
                return null;
            }
            public void checkClientTrusted(X509Certificate[] certs, String authType) {}
            public void checkServerTrusted(X509Certificate[] certs, String authType) {}
        }
    };

    private static final HostnameVerifier ALL_TRUSTING_HOSTNAME_VERIFIER  = new HostnameVerifier() {
        public boolean verify(String hostname, SSLSession session) {
            return true;
        }
    };

}

Un grand merci à: http://runtime32.blogspot.com/2008/11/let-Java-ssl-trust-all-certificates.html

11
Josh Hansen
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) {
                    }
                }
            };
            SSLContext sc = SSLContext.getInstance("SSL");
            sc.init(null, trustAllCerts, new Java.security.SecureRandom());
            HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());

            HostnameVerifier allHostsValid = new HostnameVerifier() {
                public boolean verify(String hostname, SSLSession session) {
                    return true;
                }
            };
            HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
            GetCustomerPhone http = new GetCustomerPhone(); 

    System.out.println("Processing..");     
     try{
            http.sendPost();    
        }
    catch(Exception e){
            e.printStackTrace();
        }               
}

Je pense que ça fonctionnera bien, car ça me va ...

0
Dusmant