Java client certificates over HTTPS/SSL

后端 未结 8 921
攒了一身酷
攒了一身酷 2020-11-22 13:46

I am using Java 6 and am trying to create an HttpsURLConnection against a remote server, using a client certificate.
The server is using an selfsigned root

相关标签:
8条回答
  • 2020-11-22 14:18

    While not recommended, you can also disable SSL cert validation alltogether:

    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) {}
      }
    }
    
    0 讨论(0)
  • 2020-11-22 14:18

    I use the Apache commons HTTP Client package to do this in my current project and it works fine with SSL and a self-signed cert (after installing it into cacerts like you mentioned). Please take a look at it here:

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

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

    0 讨论(0)
  • 2020-11-22 14:26

    If you are dealing with a web service call using the Axis framework, there is a much simpler answer. If all want is for your client to be able to call the SSL web service and ignore SSL certificate errors, just put this statement before you invoke any web services:

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

    The usual disclaimers about this being a Very Bad Thing to do in a production environment apply.

    I found this at the Axis wiki.

    0 讨论(0)
  • 2020-11-22 14:26

    Using below code

    -Djavax.net.ssl.keyStoreType=pkcs12
    

    or

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

    is not at all required. Also there is no need to create your own custom SSL factory.

    I also encountered the same issue, in my case there was a issue that complete certificate chain was not imported into truststores. Import certificates using keytool utility right fom root certificate, also you can open cacerts file in notepad and see if the complete certificate chain is imported or not. Check against the alias name you have provided while importing certificates, open the certificates and see how many does it contains, same number of certificates should be there in cacerts file.

    Also cacerts file should be configured in the server you are running your application, the two servers will authenticate each other with public/private keys.

    0 讨论(0)
  • 2020-11-22 14:27

    Have you set the KeyStore and/or TrustStore System properties?

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

    or from with the code

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

    Same with javax.net.ssl.trustStore

    0 讨论(0)
  • 2020-11-22 14:29

    Finally solved it ;). Got a strong hint here (Gandalfs answer touched a bit on it as well). The missing links was (mostly) the first of the parameters below, and to some extent that I overlooked the difference between keystores and truststores.

    The self-signed server certificate must be imported into a truststore:

    keytool -import -alias gridserver -file gridserver.crt -storepass $PASS -keystore gridserver.keystore

    These properties need to be set (either on the commandline, or in 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
    

    Working example 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);
    }
    
    0 讨论(0)
提交回复
热议问题