我的问题是:我有两个由 maven 构建的罐子。一个 jar 包含一个逻辑,该逻辑包装来自 jave.net.ssl 的一些类,以在 URL 中的方案为 https 时发出 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 的类中获取它之后,该类是包含上述代码的父类。获取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 中的密钥库资源中加载提供 InputStream 的 trustore,则它可以工作,但是如果另一个 jar 负责将 InputStream(带有密钥库)提供给包含 prepareSSLSocketFactory() 的依赖 jar - 它抛出异常。不知道如何处理它。
请注意,我已经通过调用检查了提供资源的类和包含 prepareSSLSocketFacory 的类是否由同一个 ClassLoader 加载:
this.getClass().getClassLoader().equals(HttpConnector.class.getClassLoader()) - 没关系。
从提供密钥库 InputStream 的类到底层的 https 请求生成类。
但是我不知道是否有可能,HttpConnector.class.getClassLoader() 返回的 ClassLoader 不是加载最后在运行时使用的 HttpConnector 的那个。