java - Tomcat java.io.IOException : Invalid keystore format when loading keystore via Classloader 异常

标签 java spring tomcat keystore

我一直在努力解决这个问题。通过 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/

相关文章:

java - 访问被拒绝,嵌入式 Derby 中的问题

java - 使 GSON 将数字反序列化为整数或 double

java - 尝试在方格网格下方添加消息 JLabel 时,GridBagLayout 做奇怪的事情

Java 类文件被截断

java - 构建后从文件启动的自定义密码策略

Tomcat 似乎没有在我的 WEB-INF/lib 文件夹中提取 jar

java - JPanel ActionMethod 显示时

java - Spring JSR-303 bean 验证不起作用,绑定(bind)结果为空

spring - NoUniqueBeanDefinitionException : No qualifying bean of type [javax. persistence.EntityManagerFactory] ​​已定义:预期单个匹配 bean

java - Eclipse Kepler x64 Debug模式 tomcat 未启动