我一直在努力解决这个问题。通过 Tomcat 上的类加载器加载 keystore 时,我不断收到无效的 keystore 格式错误。我已经编写了一些单元测试,它们成功地通过类路径加载了我的 keystore ,但是在 Tomcat 中运行时,我得到了无效的 keystore 格式错误。
这是用于 RestTemplate Spring REST 客户端的。
我的 Spring 配置代码...在单元测试和实际配置中几乎相同。
@Value("${env}")
private String env;
@Bean
public RestTemplate getRestTemplate(HttpComponentsClientHttpRequestFactory httpComponentsClientHttpRequestFactory) {
return new RestTemplate(httpComponentsClientHttpRequestFactory);
}
@Bean
public HttpComponentsClientHttpRequestFactory getHttpComponentsClientHttpRequestFactory(HttpClient httpClient) {
HttpComponentsClientHttpRequestFactory httpComponentsClientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
return httpComponentsClientHttpRequestFactory;
}
@Bean
public HttpClientConnectionManager getHttpClientConnectionManager() throws Exception {
String password = environment.getProperty("keystore.password");
InputStream cpStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(env + "/keystore.jks");
//load the keystore
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
keystore.load(cpStream, password.toCharArray());
SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(keystore).build();
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext);
PlainConnectionSocketFactory plainsf = PlainConnectionSocketFactory.getSocketFactory();
Registry<ConnectionSocketFactory> r = RegistryBuilder.<ConnectionSocketFactory>create().register("http",plainsf).register("https",sslsf).build();
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(r);
cm.setMaxTotal(200);
cm.setDefaultMaxPerRoute(50);
return cm;
}
@Bean
public HttpClient getHttpClient(HttpClientConnectionManager httpClientConnectionManager) {
return HttpClients.custom().setConnectionManager(httpClientConnectionManager).build();
}
此代码可以很好地创建我的 RestTemplate
以及单元测试中 SSLContext
所需的 keystore 。我也尝试过按照不同的方法通过我的单元测试从类加载器获取我的 keystore 的 InputStream,这些都有效。
InputStream cpStream = this.getClass().getClassLoader().getResourceAsStream(env + "/csaa.jks");
InputStream cpStream = this.getClass().getResourceAsStream("/" + env + "/csaa.jks");
env
变量只是一种加载特定环境属性的方法... env=DEV 等...。使用 JUnit SpringJUnit4ClassRunner.class< 运行它一切正常
但是在将它部署到 Tomcat 时,我总是会收到无效的 keystore 错误。如果我使用 FileInputStream
和文件系统上 keystore 的硬编码路径,它在 Tomcat 中工作得很好。我真的很想用类加载器加载它。
我也在 Liberty Profile 中尝试过,结果相同。
堆栈跟踪的相关部分:
Caused by: java.io.IOException: Invalid keystore format
at sun.security.provider.JavaKeyStore.engineLoad(JavaKeyStore.java:650)
at sun.security.provider.JavaKeyStore$JKS.engineLoad(JavaKeyStore.java:55)
at java.security.KeyStore.load(KeyStore.java:1445)
最佳答案
我发现了我的问题...我的 Maven 过滤破坏了 keystore 。我需要将以下内容添加到我的 pom.xml 中。可悲的是,我认为这不是我第一次遇到这个问题。 :(
pom.xml:
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<includes>
<include>**/*.xml</include>
</includes>
<excludes>
<exclude>**/*.jks</exclude>
</excludes>
</resource>
<resource>
<directory>src/main/resources</directory>
<filtering>false</filtering>
<includes>
<include>**/*.jks</include>
</includes>
<excludes>
<exclude>**/*.xml</exclude>
</excludes>
</resource>
</resources>
关于java - Tomcat java.io.IOException : Invalid keystore format when loading keystore via Classloader 异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30992424/