查询jvm truststore和jssecacerts文件?

时间:2012-03-24 16:05:33

标签: java ssl https

我有两个https网络应用程序app1和app2安装在两个不同的tomcats t1和t2上(t1和t2在不同的机器上)。在app1中 我建立了与app2的URL连接,我得到了SSL握手错误。原因是我在app2中使用自签名证书,但不存在 在app1 jvm truststore中。因此,正确的修复方法是在JAVA-HOME / jre / lib / security中安装自签名证书。要做的 同样,我遵循http://www.mkyong.com/webservices/jax-ws/suncertpathbuilderexception-unable-to-find-valid-certification-path-to-requested-target/给出的步骤。 不同论坛建议采取相同的步骤。但我仍然得到相同的SSL握手错误

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path   building failed: sun.security.
provider.certpath.SunCertPathBuilderException: unable to find valid certification path to   requested target
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Unknown Source)

虽然我通过在JVM信任中提及以下参数来摆脱这个SSLHandshakeException。 -Djavax.net.ssl.trustStore = C:的.keystore -Djavax.net.ssl.trustStorePassword =的changeit

我的问题是为什么第一种方法(这是正确的方法),即将/ lib / security下的jssecacerts文件放在哪里? 另一点是第一种和第二种方法有什么不同?

2 个答案:

答案 0 :(得分:6)

  

虽然我通过下面提到它摆脱了这个SSLHandshakeException   JVM信任中的参数。 -Djavax.net.ssl.trustStore = C:的.keystore   -Djavax.net.ssl.trustStorePassword =的changeit

目前尚不清楚您尝试使用这些选项。您可以使用默认信任库(通常为jssecacerts, if it exists; otherwise, cacerts),也可以指定自己的信任库。 .keystore往往被用作密钥库,而不是信任库(尽管没有默认的JSSE值)。 (顺便说一句,我也会指定完整路径而不是C:.keystore。)

制作原始cacerts(或jssecacerts)文件的副本可能更好(如果您更改了某些内容,请删除您放置的额外文件)并将远程证书添加到它(即app2副本中的app2证书和app2副本中的app1证书,如果需要的话)。

您可以使用keytool -list -keystore keystore.jks列出证书(如果需要,请参阅帮助以获取更多选项)。

您可以使用keytool -export -keystore server1-keystore.jks -alias server_alias -file server1.crt导出证书。

然后,将其导入另一个信任库:keytool -import -keystore client2-truststore.jks -file server1.crt。 (此处client2-truststore.jks将是cacerts的副本。) 然后,配置运行Apache Tomcat(不一定是Tomcat连接器)的JVM以使用它。您应该能够在catalina.shJAVA_OPTS=-D...)中设置JVM参数。

修改

  

我的问题是为什么第一种方法(这是正确的方法),即   把jssecacerts文件放在/ lib / security下是不行的?

为了更直接地回答您的问题,我只是仔细检查了干净的Oracle JRE 6安装(1.6.0_31),jssecacerts优先于cacerts(如下所述) JSSE参考指南,所以似乎没有错误)。我不确定Oracle在哪里移动了Andreas Sterbenz的Sun博客,因此我不确定您使用过哪个InstallCert副本。我想我的错在那里。

据我所知,InstallCert连接到服务器以获取其证书(替换上面的导出步骤):您有效地假设您在第一次连接时获得的证书是正确的(并且可以信任)。您还可以获得该证书using OpenSSL。但是,在您的情况下,您似乎可以控制两个服务器及其各自的密钥库,因此您也可以使用keytool -export来确定。

  

另一点是第一种和第二种方法有什么不同?

第一种方法(更改jssecacerts)为将使用此JRE安装的所有应用程序设置配置,而第二种方法仅在运行Apache Tomcat时将这些设置应用于JVM。

请注意,如果您没有jssecacerts但只有cacerts个文件,如果您只将证书导入jssecacerts,则会忽略cacerts,因此,您将无法连接到具有CA颁发的证书的服务器,而该证书通常在默认情况下是受信任的。这就是为什么从默认文件的副本开始可能是有用的。 (此外,如果您的应用程序还连接到默认情况下通常可信任的其他站点,这也可以解释为什么您这次会在不同的地方收到此错误消息。)

最终,it's your responsiblity to check what's in jssecacerts or cacerts

  

重要说明:JDK附带有限数量的受信任root   / lib / security / cacerts文件中的证书。如记录在案   keytool,你有责任维护(即添加/删除)   如果您将此文件用作此文件,则此文件中包含的证书   信任。

     

根据您联系的服务器的证书配置,   您可能需要添加其他根证书。获得所需   来自相应供应商的特定根证书。

答案 1 :(得分:0)

不同之处在于您将证书添加到不正确的信任库文件:)。 JRE的系统信任库文件不是jssecacerts,而只是在$ {JRE_HOME} / lib / security /下的cacerts。您正在创建一个JRE不知道的新信任。将证书添加到正确的商店将解决您的问题。但是,请允许我警告您,将自定义CA证书添加到系统信任库不是一个好主意。将它们添加到用户信任库,并按照您在第二个选项中使用的方式使用它。