124 votes

Certificats client Java via HTTPS / SSL

Je suis à l'aide de Java 6 et je suis en train de créer un HttpsURLConnection sur un serveur distant, à l'aide d'un certificat client.
Le serveur est à l'aide d'un autosignés certificat racine, et nécessite un mot de passe protégé certificat client est présenté. J'ai ajouté le certificat racine du serveur et le certificat du client pour un java par défaut du fichier de clés que j'ai trouvé, en /System/Library/Frameworks/JavaVM.framework/Versions/1.6.0/Home/lib/security/cacerts (OSX 10.5). Le nom du fichier de magasin de clés semble suggérer que le certificat du client n'est pas censé y aller?

De toute façon, ajouter le certificat racine de ce magasin résolu le tristement célèbre javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed' problem.

Cependant, je suis maintenant coincé sur la façon d'utiliser le certificat client. J'ai essayé les deux approches et obtient ni moi n'importe où.
Tout d'abord, et préféré, essayez:

SSLSocketFactory sslsocketfactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
URL url = new URL("https://somehost.dk:3049");
HttpsURLConnection conn = (HttpsURLConnection)url.openConnection();
conn.setSSLSocketFactory(sslsocketfactory);
InputStream inputstream = conn.getInputStream();
// The last line fails, and gives:
// javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure

J'ai essayé de sauter le HttpsURLConnection classe (pas l'idéal, car je veux parler HTTP avec le serveur), et faire ceci à la place:

SSLSocketFactory sslsocketfactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
SSLSocket sslsocket = (SSLSocket) sslsocketfactory.createSocket("somehost.dk", 3049);
InputStream inputstream = sslsocket.getInputStream();
// do anything with the inputstream results in:
// java.net.SocketTimeoutException: Read timed out

Je ne suis même pas sûr que le certificat client est le problème ici.

107voto

Jan Points 1246

Enfin résolu ;). Eu une forte allusion ici (Gandalfs réponse touché un peu sur elle aussi bien). Les chaînons manquants a été (pour la plupart) le premier des paramètres ci-dessous, et dans une certaine mesure, que j'ai négligé la différence entre les fichiers de clés et truststores.

L'auto-signé certificat de serveur doit être importé dans un truststore:

keytool -import-alias gridserver -fichier gridserver.crt -storepass $PASS -keystore gridserver.fichier de clés

Ces propriétés doivent être définies sur la ligne de commande, ou dans le code):

-Djavax.net.ssl.keyStoreType=pkcs12
-Djavax.net.ssl.trustStoreType=jks
-Djavax.net.ssl.keyStore=clientcertificate.p12
-Djavax.net.ssl.trustStore=gridserver.keystore
-Djavax.net.debug=ssl # very verbose debug
-Djavax.net.ssl.keyStorePassword=$PASS
-Djavax.net.ssl.trustStorePassword=$PASS

Exemple de code:

SSLSocketFactory sslsocketfactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
URL url = new URL("https://gridserver:3049/cgi-bin/ls.py");
HttpsURLConnection conn = (HttpsURLConnection)url.openConnection();
conn.setSSLSocketFactory(sslsocketfactory);
InputStream inputstream = conn.getInputStream();
InputStreamReader inputstreamreader = new InputStreamReader(inputstream);
BufferedReader bufferedreader = new BufferedReader(inputstreamreader);

String string = null;
while ((string = bufferedreader.readLine()) != null) {
    System.out.println("Received " + string);
}

85voto

neu242 Points 4538

Bien que cela ne soit pas recommandé, vous pouvez également désactiver la validation du certificat SSL dans son intégralité:

 import javax.net.ssl.*;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;

public class SSLTool {

  public static void disableCertificateValidation() {
    // Create a trust manager that does not validate certificate chains
    TrustManager[] trustAllCerts = new TrustManager[] { 
      new X509TrustManager() {
        public X509Certificate[] getAcceptedIssuers() { 
          return new X509Certificate[0]; 
        }
        public void checkClientTrusted(X509Certificate[] certs, String authType) {}
        public void checkServerTrusted(X509Certificate[] certs, String authType) {}
    }};

    // Ignore differences between given hostname and certificate hostname
    HostnameVerifier hv = new HostnameVerifier() {
      public boolean verify(String hostname, SSLSession session) { return true; }
    };

    // Install the all-trusting trust manager
    try {
      SSLContext sc = SSLContext.getInstance("SSL");
      sc.init(null, trustAllCerts, new SecureRandom());
      HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
      HttpsURLConnection.setDefaultHostnameVerifier(hv);
    } catch (Exception e) {}
  }
}
 

21voto

Gandalf Points 4909

Avez-vous défini les propriétés du système KeyStore et / ou TrustStore?

 java -Djavax.net.ssl.keyStore=pathToKeystore -Djavax.net.ssl.keyStorePassword=123456
 

ou de avec le code

 System.setProperty("javax.net.ssl.keyStore", pathToKeyStore);
 

Pareil avec javax.net.ssl.trustStore

13voto

Mark Meuer Points 1172

Si vous avez affaire à un appel de service web à l'aide de l'Axe de cadre, il est beaucoup plus simple de répondre. Si tous voulez pour votre client d'être en mesure d'appeler le service web SSL et ignorer certificat SSL erreurs, il suffit de mettre cette déclaration avant d'appeler les services web:

System.setProperty("axis.socketSecureFactory", "org.apache.axis.components.net.SunFakeTrustSocketFactory");

Les avertissements habituels sur ce qui est une Très Mauvaise Chose à faire dans un environnement de production s'appliquent.

J'ai trouvé ce à l'Axe wiki.

4voto

Taylor Leese Points 18895

J'utilise le paquet HTTP Client Apache commons pour le faire dans mon projet actuel et cela fonctionne bien avec SSL et un certificat auto-signé (après l'avoir installé dans cacerts, comme vous l'avez mentionné). S'il vous plaît jetez un coup d'oeil ici:

http://hc.apache.org/httpclient-3.x/tutorial.html

http://hc.apache.org/httpclient-3.x/sslguide.html

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