Load java trust store at runtime - after jvm have

2019-05-10 10:49发布

In my java application I need to send POST requests to a server sitting behind https. On the machine where my java application is running there is a java trust store in: /usr/local/comp.jks that contains the certificate for the server I need to interact with (its already imported).

The problem is that I cannot control how the JVM is started that will run my java application - e.g. by adding:

-Djavax.net.ssl.trustStore=/usr/local/comp.jks to the VM arguments.

Is it possible to load the trust store in the above path at runtime from my application after the JVM has started so I can authenticate against the https site?

I have only found guides on how to import certificates at runtime but that I cannot use - also since I don't have the password for /usr/local/comp.jks

Below my current implementation (in groovy):

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.KeyStore
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException
import java.security.cert.X509Certificate
import java.util.Base64;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;


public class HttpsClientImpl extends AbstractHttpClient  {
  private String username = null;
  private String password = null;

  public HttpsClientImpl (String username, String password)  {
    this.username=username;
    this.password=password;

  }

  @Override
  public String sendRequest(String request, String method) {
    System.setProperty( "javax.net.ssl.trustStore", "/usr/local/comp.jks" );
    URL url = new URL(request);
    HttpsURLConnection con = (HttpsURLConnection) url.openConnection()
    // Set auth
    byte[] name = (username + ":" + password).getBytes();
    String authStr = Base64.getEncoder().encodeToString(name);
    con.setRequestProperty("Authorization", "Basic " + authStr)

    con.setRequestMethod(method);
    writeResult(con);
    return con.getResponseCode();
  }


  private void writeResult(HttpsURLConnection con) throws IOException {
    if(con!=null){
      BufferedReader br = null;
      if (200 <= con.getResponseCode() && con.getResponseCode() <= 299) {
        br = new BufferedReader(new InputStreamReader(con.getInputStream()));
      } else {
        br = new BufferedReader(new InputStreamReader(con.getErrorStream()));
      }
      try {
        String input;
        while ((input = br.readLine()) != null){
          System.out.println(input);
        }
        br.close();
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
  }
}

When I run that I get:

sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:141)
    at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126)
    at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280)
    at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:382)
Caused: sun.security.validator.ValidatorException: PKIX path building failed

标签: java ssl https
2条回答
可以哭但决不认输i
2楼-- · 2019-05-10 10:57

Assuming you haven't instantiated any SSL connections yet, you can simply call

System.setProperty( "javax.net.ssl.trustStore", "/usr/local/comp.jks" );

You'll probably also need to set javax.net.ssl.trustStorePassword and maybe javax.net.ssl.trustStoreType.

If the default SSL infrastructure has alredy been instantiated, you'll probably have to create your own SSLContext and SSLSocketFactory using your keystore.

查看更多
家丑人穷心不美
3楼-- · 2019-05-10 11:04

You can do so by initializing key store like below:-

SSLContext sslContext = null;

String keyStorePath = "/usr/local/comp.jks";
String trustStorePath = "/usr/local/comp.jks";
String keyStorePw = "????";//put your key store password
String trustStorePw = "????";//put your truststore password
String keyPass = "????";//put your certificate key password


sslContext = initializeSSLContext(keyStorePath, keyStorePw, trustStorePath, trustStorePw, keyPass);

URL obj;
HttpsURLConnection conn = null;

try {
    obj = new URL(null , url, new sun.net.www.protocol.https.Handler());
} catch (MalformedURLException e) {
    System.out.println("MalformedURLException occurred " + e.getMessage());
}

conn=(HttpsURLConnection) obj.openConnection();
conn.setSSLSocketFactory(sslContext.getSocketFactory());


private SSLContext initializeSSLContext(final String keyStorePath, final String pwKeyStore, final String trustStorePath, final String pwTrustStore, final String keyPass, final boolean trustall) {

        char[] keyStorePw = pwKeyStore.toCharArray();
        char[] trustStorePw = pwTrustStore.toCharArray();
        char[] keyPw = keyPass.toCharArray();

        SecureRandom secureRandom = new SecureRandom();
        secureRandom.nextInt();

        KeyStore ks = null;
        try {
            ks = KeyStore.getInstance("JKS");
        } catch (KeyStoreException exp) {
            System.out.println("SSLContextUtil::KeyStoreException exception occurred while reading the config file : " +exp.getMessage());
        }
        FileInputStream fis = null;
        try {
            try {
                fis = new FileInputStream(keyStorePath);
            } catch (FileNotFoundException exp) {
                System.out.println("SSLContextUtil::FileNotFoundException exception occurred " +exp.getMessage());
            }
            try {
                ks.load(fis, keyStorePw);
            } catch (NoSuchAlgorithmException exp) {
                System.out.println("SSLContextUtil::NoSuchAlgorithmException exception occurred " +exp.getMessage());
            } catch (CertificateException exp) {
                System.out.println("SSLContextUtil::CertificateException exception occurred " +exp.getMessage());
            } catch (IOException exp) {
                System.out.println("SSLContextUtil::CertificateException exception occurred " +exp.getMessage());
            }           
        } finally {
            if (fis != null)
                try {
                    fis.close();
                } catch (IOException exp) {
                    System.out.println("SSLContextUtil::IOException exception occurred " +exp.getMessage());
                }
        }

        System.out.println.info("SSLContextUtil::[initializeSSLContext] KMF keystorepw loaded.");

        KeyManagerFactory kmf = null;
        try {
            kmf = KeyManagerFactory.getInstance("SunX509");
        } catch (NoSuchAlgorithmException exp) {
            System.out.println("SSLContextUtil::IOException exception occurred " +exp.getMessage());
        }
        try {
            kmf.init(ks, keyPw);
        } catch (UnrecoverableKeyException exp) {
            System.out.println("SSLContextUtil::UnrecoverableKeyException exception occurred " +exp.getMessage());
        } catch (KeyStoreException exp) {
            System.out.println("SSLContextUtil::KeyStoreException exception occurred " +exp.getMessage());
        } catch (NoSuchAlgorithmException exp) {
            System.out.println("SSLContextUtil::NoSuchAlgorithmException exception occurred " +exp.getMessage());
        }

        System.out.println.info("SSLContextUtil::[initializeSSLContext] KMF init done.");

        KeyStore ts = null;
        try {
            ts = KeyStore.getInstance("JKS");
        } catch (KeyStoreException exp) {
            System.out.println("SSLContextUtil::NoSuchAlgorithmException exception occurred " +exp.getMessage());
        }
        FileInputStream tfis = null;
        SSLContext sslContext = null;
        try {
            tfis = new FileInputStream(trustStorePath);
            ts.load(tfis, trustStorePw);
            TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
            tmf.init(ts);
            System.out.println.info("SSLContextUtil::[initializeSSLContext] Truststore initialized");
            sslContext = SSLContext.getInstance("TLS");         

            sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers() ,secureRandom);

        } catch (NoSuchAlgorithmException exp) {
            System.out.println("SSLContextUtil::NoSuchAlgorithmException exception occurred " +exp.getMessage());
        } catch (CertificateException exp) {
            System.out.println("SSLContextUtil::NoSuchAlgorithmException exception occurred " +exp.getMessage());
        } catch (IOException exp) {
            System.out.println("SSLContextUtil::NoSuchAlgorithmException exception occurred " +exp.getMessage());
        } catch (KeyStoreException exp) {
            System.out.println("SSLContextUtil::NoSuchAlgorithmException exception occurred " +exp.getMessage());
        } catch (KeyManagementException exp) {
            System.out.println("SSLContextUtil::NoSuchAlgorithmException exception occurred " +exp.getMessage());
        } finally {
            if (tfis != null)
                try {
                    tfis.close();
                } catch (IOException exp) {
                    System.out.println("SSLContextUtil::NoSuchAlgorithmException exception occurred " +exp.getMessage());
                }
        }

        if((sslContext == null)){
            System.out.println("SSLContextUtil::[initializeSSLContext] sslContext is null");
        }
        return sslContext;
    }
查看更多
登录 后发表回答