如何使用来自另一个jar的资源加载密钥库。

时间:2012-11-16 10:33:32

标签: ssl https classloader keystore httpsurlconnection

我的问题我跟随:我有两个由maven建造的罐子。一个jar包含一个逻辑,当URL中的scheme为https时,它会从jave.net.ssl包装一些类来生成https请求:获取HttpsUrlConnection之后,我将获得如下所示的SSLSocketFactory:

private SSLSocketFactory prepareSSLSocketFactory(SecurityConfig secConfig) throws NoSuchAlgorithmException, CertificateException, IOException, KeyStoreException, KeyManagementException
{
    if (secConfig == null) throw new IllegalArgumentException("secConfig");
    if (sslSocketFactory!=null)
        return sslSocketFactory;

    KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());      
    trustStore.load(secConfig.getSslTrustStore()/*ClassLoader.getSystemClassLoader().getResourceAsStream("jclienttruststore.jks")*/, secConfig.getSslTrustStorePassword().toCharArray());

    TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
    tmf.init(trustStore);
    SSLContext ctx = SSLContext.getInstance(secConfig.getSslAlgorithm());
    ctx.init(null, tmf.getTrustManagers(), null);
    sslSocketFactory = ctx.getSocketFactory();
    return sslSocketFactory;
}

注意部分secConfig.getSslTrustStore(),因为它包含传入此方法的InputStream,在jar中从jar获取它之后,它是包含上述代码的jar的父类。获取InputStream如下:

protected InputStream obtainTrustStore() 
{                
    //InputStream stream = this.getClass().getClassLoader().getParent().getResourceAsStream("trustcert/jclienttruststore.jks");
    //InputStream stream = ClassLoader.getSystemClassLoader().getResourceAsStream("trustcert/jclienttruststore.jks");

    InputStream stream = this.getClass().getClassLoader().getResourceAsStream("trustcert/jclienttruststore.jks");
    return stream;
}       

资源已成功定位,并获取InputStream。但是当谈到在第一个片段上执行trustStore.load()时,我得到奇怪的异常,说KeyStoreFormat无效。 KeyStoreFormat是有效的 - 这是肯定的 - 因为当我从包含此prepareSSLSocketFactory的jar执行测试方法并加载相同的密钥库文件但位于当前jar的资源时,根本没有异常,并且客户端成功通过ssl进行通信。

所以,我的观察结果如下:如果我从正在执行方法prepareSSLSocketFactory的jar中的keystore资源加载给出InputStream的trustore它可以工作,但是如果另一个jar负责向包含prepareSSLSocketFactory的依赖jar提供InputStream(带有keystore)( ) - 它抛出异常。 不知道如何处理它。

请注意,我已经检查了提供资源的类和包含prepareSSLSocketFacory的类是否由同一个ClassLoader通过调用加载:

this.getClass()。getClassLoader()。equals(HttpConnector.class.getClassLoader()) - 没问题。

从类中提供密钥库InputStream到底层的https请求制作类。

但是我不知道是否有可能HttpConnector.class.getClassLoader()返回的ClassLoader不是加载最后在运行时使用的HttpConnector的类。

1 个答案:

答案 0 :(得分:0)

问题现在已经解决了......更重要的是 - 答案并非真实。问题与加载相同密钥库资源的不同类加载器无关,实际上资源之一(通过资源我的意思是keytool生成的密钥库文件)在运行时被简单地损坏(因此异常“密钥库格式无效”是可以的)。这很难解决,因为密钥库只生成一次,然后文件被复制到资源文件夹。所以我假设它不会被破坏 - 它不是 - 因为我重建项目 - 在我的maven构建中我有一个资源插件,它为所有资源启用了过滤 - 这使得每次我构建项目时密钥库文件都被破坏了:)