【问题标题】:Where to put keystore for Tomcat web app using Apache HTTP client使用 Apache HTTP 客户端为 Tomcat Web 应用程序放置密钥库的位置
【发布时间】:2023-03-08 15:33:01
【问题描述】:

我正在编写一个访问远程服务器的例程。我要连接的这台服务器需要相互身份验证,因此我必须提供一个密钥库,并且在使用它的同时,我还想建立一个适当的信任库。

我可以找到很多关于如何使用keytool 创建密钥库的教程,以及让 Apache HTTP 客户端识别它的多种方法,但找不到在 Tomcat 环境中将其存储在何处以便应用程序可以找到它。不知何故,将它放在应用程序的 war 文件中对我来说似乎是个坏主意。

再次重申,这并不是为了让 Tomcat 处理入站 https 连接 - 我的管理团队为此设置了一个反向代理。我正在创建需要相互身份验证的传出 https 连接,即接受自签名目标服务器证书并提供我的服务器的自签名客户端证书。

您在 Tomcat 环境中将实际的密钥库和信任库文件存储在哪里以供 Web 应用程序使用?

【问题讨论】:

  • Java 提供的尚未满足的“适当的信任库”到底是什么意思?
  • 那是题外话,但我连接到的服务提供了一个自签名证书,这是 cacert 默认不接受的。我目前“全部接受”,但他们已经打开了相互,现在我还必须提供我自己的客户端自签名,所以如果我必须为密钥库添加管道,那么我应该利用这个机会添加信任库支持好吧。首先我需要知道把这些该死的东西放在哪里。
  • 据我所知,keystore文件可以在服务器可以读取的目录路径中的任何位置。在tomcat的server.xml中,您需要在连接器端口8443中指定目录路径属性 Keystorefile。
  • @Amz 用于客户端 TLS 证书的密钥库与 Tomcat 的 <Connector> 配置无关。这不是 Tomcat 配置问题。

标签: java tomcat keystore apache-httpclient-4.x truststore


【解决方案1】:

只要您知道如何告诉httpclient 将密钥库加载到哪里,您就可以将您的密钥库放在任何位置。

当然,这就是诀窍。

Using Apache httpclient for https

隐藏在已接受答案中的所有代码中是使用httpclient 和您自己的自定义密钥库的关键(哈!)。不幸的是,httpclient 没有简单的 API,例如“这是我的密钥库文件的路径,现在使用它”或“这是我的密钥库的字节,使用那些”(如果您想从ClassLoader 或其他),但似乎是这样。

诚实的事实是,在 Java 中使用密钥库和信任库是一件很麻烦的事情,而且通常没有办法绕过它。我自己写了一个client-cert-capable HTTP client,只使用了 HttpsURLConnection,然后还添加了 raw-socket 组件,我知道这有多痛苦。

上面链接的文章中的代码虽然有点冗长,但还是相当简单的。不幸的是,您将需要使生产质量代码变得更加混乱,因为您必须对流程的每个步骤进行错误检查等,以确保您的服务在以下情况下不会崩溃您正在尝试设置各种商店并建立联系。

【讨论】:

  • 请看我的帖子,基本上是对您的回答的评论。否则为您的答案 +1。
【解决方案2】:

这基本上是对Christopher Schultz's answer的评论,但由于涉及到一些代码sn-ps,请原谅我放在这里

很遗憾 httpclient 没有像这样的简单 API “这是我的密钥库文件的路径,现在使用它”或“这是 我的密钥库的字节,使用那些“(如果你想加载密钥库 从 ClassLoader 或其他),但似乎是这样

这是配置 Apache HttpClient 4.3 以使用特定信任库进行 SSL 上下文初始化的方式。

SSLContext sslContext = SSLContexts.custom()
        .loadTrustMaterial(trustStore)
        .build();
CloseableHttpClient client = HttpClients.custom()
        .setSslcontext(sslContext)
        .build();

可以从类似的资源中加载信任材料

URL resource = getClass().getResource("/com/mycompany/mystuff/my.truststore");
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
InputStream inputStream = resource.openStream();
try {
    trustStore.load(inputStream, null /*usually not password protected*/);
} finally {
    inputStream.close();
}

【讨论】:

  • 感谢更新的代码 sn-ps。如果HttpClient 的人没有隐藏他们的Javadoc,我可能已经能够搜索任何存在的适用方法(或者,在这种情况下,构建器)。 :(
猜你喜欢
  • 2012-09-06
  • 1970-01-01
  • 2012-04-04
  • 2016-02-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-16
相关资源
最近更新 更多