avr 20

[Java] Apache HttpClient et SSL non valide

Catégorie(s): DéveloppementSébastien @ 20:48

Dans une partie de l’application sur laquelle je bosse actuellement, je dois interroger un site via le protocole HTTP et HTTPS. Pour cela, on m’a conseillé la classe HttpClient développée par Apache. Très bon conseil : elle fait vraiment bien son boulot et est très simple à prendre en main. Mais dès que je suis passé en HTTPS, je me suis retrouvé avec une jolie erreur : « SSLPeerUnverifiedException: peer not authenticated« . J’ai cherché d’où ça pouvait bien venir en me penchant sur le certificat vu que c’est la seule chose qui changeait par rapport au HTTP. Il me paraissait normal jusqu’à temps que je me souvienne que j’ai dû ajouter une exception dans Firefox pour pouvoir accéder à ce site. En cherchant un peu plus loin (propriétés du certif), le problème vient du fait qu’il soit périmé. Il n’est donc plus valide donc HttpClient lève une exception et donc ça plante.

Le problème c’est que j’ai quand même besoin d’y accéder ! Voici donc une solution qui consiste à implémenter son propre vérificateur de validité de certificat et le mettre par défaut ensuite. Ça se passe dans deux classes.

MyX509TrustManager.java

package com.dra.core;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.X509TrustManager;
public class MyX509TrustManager implements X509TrustManager {
    @Override
    public void checkClientTrusted(X509Certificate[] arg0, String arg1)
            throws CertificateException {
    }
    @Override
    public void checkServerTrusted(X509Certificate[] arg0, String arg1)
            throws CertificateException {
    }
    @Override
    public X509Certificate[] getAcceptedIssuers() {
        // TODO Auto-generated method stub
        return null;
    }
}

Tout bête : on implémente l’interface X509TrustManager mais on ne fait rien. Etant donné qu’aucune erreur est levée, le certificat est considéré comme valide.

La classe suivante est simplement une classe me permettant de gérer la mise par défaut ou non de la classe crée ci-dessus.

MyTrustManager.java

package com.dra.core;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManager;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
public class MyTrustManager {
    protected static SSLSocketFactory _oldSSLSocketFactory = null;
    public static void enable() {
        if(_oldSSLSocketFactory != null) {
            HttpsURLConnection.setDefaultSSLSocketFactory(_oldSSLSocketFactory);
        }
    }
    public static void disable() {
        // Save the old SSLSocketFactory
        _oldSSLSocketFactory = HttpsURLConnection.getDefaultSSLSocketFactory();
        try {
            // New X509TrustManager (our manager)
            X509TrustManager x509tm = new MyX509TrustManager();
            // Needed by SSLContext :
            KeyManager[] keyManager = null;
            // Set trust manager :
            TrustManager[] trustManager= {x509tm};
            // Get the SSLContext
            SSLContext sslContent = SSLContext.getInstance("ssl");
            // Initializaton of the SSLContext
            sslContent.init(keyManager, trustManager, new java.security.SecureRandom());
            // Get the SSLSocketFactory of our new SSLContext
            SSLSocketFactory socketFactory = sslContent.getSocketFactory();
            // Set this new SSLSocketFactory as default
            HttpsURLConnection.setDefaultSSLSocketFactory(socketFactory);
        } catch (KeyManagementException exp) {
            exp.printStackTrace();
        } catch (NoSuchAlgorithmException exp) {
            exp.printStackTrace();
        }
    }
}

Attention quand même, il faut être sûr de votre source quand vous faites ça…

Articles sur le même sujet :

  1. [Post-it] Convertir un WSDL (RPC-Encoding) en fichier Java
  2. [Java] HttpClient 4 et authentification HTTP
  3. [Pentaho] Lancer une transformation depuis un servlet
  4. [Java / Pentaho BI Server] Déployer ses propres JSP et servlet

7 Responses to “[Java] Apache HttpClient et SSL non valide”

  1. Olivier B.

    Et ben je vois que tu t’éclates mon petit ! Moi je tape dans une application web qui génère des Excel, qui récupère ses données dans une base oracle complètement folle (au bout de 20 ans c’est un peu normal…) et donc la page d’accueil n’était qu’un simple fichier PHP de…. 7000 lignes ! \o/
    Bref, je m’éclate aussi et j’avance bien plus vite que leurs espérances… Qui a dit que je bossais comme un fou en espérant des primes?
    Bonne continuation mec !

  2. Sébastien

    Je m’éclate comme un petit fou ouai ! Et encore, je pense que ça c’est une partie assez simple du projet sur lequel je bosse. :/

    Ton projet a l’air d’être sympa aussi, ça m’aurait bien plu de pouvoir faire du PHP, plus simple. ^^’

    Amuse toi bien. ;)

  3. LG

    Hé beh, t’es encore plus geek que ce que je craignais… ;)

  4. Sébastien

    Ca aurait pu être pire… j’aurai pu faire ça pour le fun alors que là c’est pour mon stage. :p

  5. Zoie

    Well written article.

  6. docv266

    Alors là tu m’as bien bien aidé!

    Merci

  7. Sébastien

    Mais de rien, ça fait plaisir de pouvoir aider. :)

Laisser un commentaire