How to use a file in a jar as javax.net.ssl.keystore?

前提是你 提交于 2019-12-17 10:43:06

问题


I'm trying to do something like

URL clientks = com.messaging.SubscriptionManager.class.getResource( "client.ks" );
String path = clientks.toURI().getPath();
System.setProperty( "javax.net.ssl.keyStore", path);

Where client.ks is a file stored in com/messaging in the jar file that I'm running.

The thing that reads the javax.net.ssl.keyStore is expecting a path to the client.ks file which is in the jar. I'd rather not extract the file and put in on the client's machine if possible. So is it possible to reference a file in a jar?

This doesn't work as getPath() returns null. Is there another way to do this?


回答1:


Still working on implementation, but I believe it is possible to load the keystore from the jar via InputStream and explicitly set the TrustStore programatically (vs setting the System properties). See the article: Setting multiple truststore on the same JVM

Got it working!

InputStream keystoreInput = Thread.currentThread().getContextClassLoader()
    .getResourceAsStream(<path in jar>/client.ks");
InputStream truststoreInput = Thread.currentThread().getContextClassLoader()
    .getResourceAsStream(<path in jar>/client.ts");
setSSLFactories(keystoreInput, "password", truststoreInput);
keystoreInput.close();
truststoreInput.close();

private static void setSSLFactories(InputStream keyStream, String keyStorePassword, 
    InputStream trustStream) throws Exception
{    
  // Get keyStore
  KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());    

  // if your store is password protected then declare it (it can be null however)
  char[] keyPassword = keyStorePassword.toCharArray();

  // load the stream to your store
  keyStore.load(keyStream, keyPassword);

  // initialize a key manager factory with the key store
  KeyManagerFactory keyFactory = 
  KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());    
  keyFactory.init(keyStore, keyPassword);

  // get the key managers from the factory
  KeyManager[] keyManagers = keyFactory.getKeyManagers();

  // Now get trustStore
  KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());    

  // if your store is password protected then declare it (it can be null however)
  //char[] trustPassword = password.toCharArray();

  // load the stream to your store
  trustStore.load(trustStream, null);

  // initialize a trust manager factory with the trusted store
  TrustManagerFactory trustFactory = 
  TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());    
  trustFactory.init(trustStore);

  // get the trust managers from the factory
  TrustManager[] trustManagers = trustFactory.getTrustManagers();

  // initialize an ssl context to use these managers and set as default
  SSLContext sslContext = SSLContext.getInstance("SSL");
  sslContext.init(keyManagers, trustManagers, null);
  SSLContext.setDefault(sslContext);    
}



回答2:


You can get an InputStream to a resource in a jar file, but not a File. If the "thing" that ultimately reads the keystore expects a File or a path to a file, your only option is to extract it to the filesystem.




回答3:


Here's a cleaned-up version of user2529737's answer, in case it helps. It has removed unneeded trust store setup and added required imports, parameters for keystore type and key password.

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.security.KeyStore;

public class PlainJavaHTTPS2Test {

    public void setUp() throws Exception {
        final String KEYSTOREPATH = "clientkeystore.p12"; // or .jks

        // store password can be null if there is no password
        final char[] KEYSTOREPASS = "keystorepass".toCharArray();

        // key password can be null if there is no password
        final char[] KEYPASS = "keypass".toCharArray();

        try (InputStream storeStream = this.getClass().getResourceAsStream(KEYSTOREPATH)) {
            setSSLFactories(storeStream, "PKCS12", KEYSTOREPASS, KEYPASS);
        }
    }
    private static void setSSLFactories(InputStream keyStream, String keystoreType, char[] keyStorePassword, char[] keyPassword) throws Exception
    {
        KeyStore keyStore = KeyStore.getInstance(keystoreType);

        keyStore.load(keyStream, keyStorePassword);

        KeyManagerFactory keyFactory =
                KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());

        keyFactory.init(keyStore, keyPassword);

        KeyManager[] keyManagers = keyFactory.getKeyManagers();

        SSLContext sslContext = SSLContext.getInstance("SSL");
        sslContext.init(keyManagers, null, null);
        SSLContext.setDefault(sslContext);
    }
}


来源:https://stackoverflow.com/questions/344748/how-to-use-a-file-in-a-jar-as-javax-net-ssl-keystore

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!