5 votes

Exception lors de l'impression des détails du certificat du serveur

J'ai mis en place une connexion https entre le serveur et le client, où le client est un programme java et le serveur est une servlet. J'ai utilisé le code suivant pour imprimer les détails du certificat à partir du serveur.

URL url = new URL("https://localhost:8443/cert");
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
connection.setSSLSocketFactory(sslsocketfactory);

connection.setDoOutput(true);
if(connection!=null){
    Certificate[] certs = connection.getServerCertificates();// #1 

    System.out.println("Cert Type : " + certs[0].getType());
    System.out.println("Cert Hash Code : " + certs[0].hashCode());
    System.out.println("Cert Public Key Algorithm : " + certs[0].getPublicKey().getAlgorithm());
    System.out.println("Cert Public Key Format : " + certs[0].getPublicKey().getFormat());
    System.out.println("\n");
}

Mais j'obtiens l'exception suivante.

java.lang.IllegalStateException: connection not yet open

Je pensais que la poignée de main devait avoir lieu dès l'appel de la méthode url.openconnection(). Quel est le problème ici ?
L'exception est lancée à la ligne numéro '#1' (voir les commentaires dans le code ci-dessus).

3voto

Petesh Points 29374

Vous essayez de vous connecter à un hôte avec un certificat auto-signé. Suivez les instructions de l'option 2 de la réponse de cette réponse qui devrait vous permettre de vous connecter.

J'ai remplacé le connection.setDoOutput() avec un connection.connect() et le code a fonctionné correctement pour moi.

N'utilisez pas ce mécanisme pour autre chose que des tests - vous devez utiliser un certificat validement signé.

3voto

Bruno Points 47560

La poignée de main d'un SSLSocket " [...] peut être initié de l'une des trois manières suivantes : "

  • en appelant startHandshake qui commence explicitement les échanges de mains, ou
  • toute tentative de lecture ou d'écriture de données d'application sur cette socket provoque un handshake implicite, ou
  • un appel à getSession tente de configurer une session s'il n'y a pas de session valide actuellement, et une poignée de main implicite est effectuée.

Il semble que la seule applicable via HttpsURLConnection est d'essayer de lire/écrire quelque chose (puisque vous ne pouvez pas mettre la main sur les données sous-jacentes). SSLSocket directement pour commencer le handshake ou obtenir la session).

Si vous appelez juste connection.getInputStream(); avant d'essayer d'obtenir le certificat, cela devrait initier la poignée de main, et vous obtiendrez les certificats par la suite.

Notez que vous n'atteindrez ce point que si le certificat que vous voulez voir est reconnu par votre entreprise. SSLContext / SSLSocketFactory . Pour ce faire, vous pouvez construire un keystore (que vous utiliserez comme truststore) qui contient ce certificat, comme décrit dans cette réponse . Vous pouvez utiliser si de votre propre SSLContext ou l'utiliser globalement via l'option javax.net.ssl.trustStore* propriétés du système (à définir avant toute utilisation de SSL). Évitez les exemples de TrustManagers qui ne vérifient rien (il y en a quelques-uns ici sur SO) : cela désactivera tout simplement la vérification du certificat, rendant la connexion potentiellement vulnérable aux attaques MITM.

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