【问题标题】:How to use a file in a jar as javax.net.ssl.keystore?如何将 jar 中的文件用作 javax.net.ssl.keystore?
【发布时间】:2010-09-25 13:50:23
【问题描述】:

我正在尝试做类似的事情

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

其中 client.ks 是我正在运行的 jar 文件中存储在 com/messaging 中的文件。

读取 javax.net.ssl.keyStore 的东西需要一个指向 jar 中 client.ks 文件的路径。如果可能的话,我宁愿不提取文件并放入客户端的机器上。那么是否可以引用 jar 中的文件?

这不起作用,因为 getPath() 返回 null。还有其他方法吗?

【问题讨论】:

  • 标题具有误导性。看起来您在询问是否可以在 jar 文件中获取对资源的文件引用; System.setProperty 调用无关紧要。

标签: java jar executable-jar


【解决方案1】:

您可以在 jar 文件中获取资源的 InputStream,但不能获取 File。如果最终读取密钥库的“事物”需要 File 或文件路径,那么您唯一的选择是将其提取到文件系统中。

【讨论】:

  • 好的,谢谢!这就是我在此期间所做的,而且效果很好;它只是不那么干净。
【解决方案2】:

仍在努力实现,但我相信可以通过 InputStream 从 jar 加载密钥库并以编程方式显式设置 TrustStore(与设置系统属性相比)。见文章:Setting multiple truststore on the same JVM

搞定了!

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);    
}

【讨论】:

  • 谢谢!我一直在寻找解决方案,而我看到的所有其他事情看起来都太复杂了:)
  • 干得好,但应注意您使用了两次 keyStorePassword。作为密钥库密码和私钥密码,并非总是如此。
  • 我添加了一个新参数“String keyPassphrase”并将一行更改为 keyFactory.init(keyStore, keyPassphrase.toCharArray());
【解决方案3】:

这是user2529737's answer 的清理版本,以防万一。它删除了不需要的信任库设置并添加了必需的导入、密钥库类型和密钥密码的参数。

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);
    }
}

【讨论】:

  • (我在考虑是否应该将其作为自己的答案,但在阅读this 后,我选择将其作为自己的答案)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-07
  • 2012-04-19
  • 1970-01-01
  • 2010-10-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多