我有两个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文件放在哪里? 另一点是第一种和第二种方法有什么不同?
答案 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.sh
(JAVA_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证书添加到系统信任库不是一个好主意。将它们添加到用户信任库,并按照您在第二个选项中使用的方式使用它。