使用Java客户端访问Tomcat HTTPS URL

时间:2014-08-08 16:57:27

标签: java tomcat ssl

我已经将我的Tomcat实例配置为在端口8443上使用SSL。我已经通过在我的浏览器上通过https:8443访问主tomcat页面来验证它正在工作。

现在我正在尝试了解我需要做什么才能让Java程序从该tomcat服务器上的HTTPS URL读取。我按照这里的说明进行操作:

Java SSL Tutorial

我刚刚将.keystore文件复制到我在我的Web服务器上使用Java的keytool生成的客户端。它是自签名的,仅用于开发工作。这对我来说有点奇怪,因为那里也有私钥,对吗?我以为我会做一些事情来导出公钥并把它放在我的客户端上,但我找不到一个很好的指导,我需要采取什么步骤。

无论如何,当我尝试在我的客户端上使用我的服务器上生成的.keystore时,我收到此错误:

***
%% Invalidated:  [Session-1, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA]
main, SEND TLSv1 ALERT:  fatal, description = certificate_unknown
main, WRITE: TLSv1 Alert, length = 2
main, called closeSocket()
main, handling exception: 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
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 sun.security.ssl.Alerts.getSSLException(Unknown Source)

我已将我的客户端设置为使用这些JVM args运行:

-Djavax.net.ssl.keyStore=.keystore  -Djavax.net.ssl.keyStorePassword=changeit -Djava.protocol.handler.pkgs=com.sun.net.ssl.internal.www.protocol -Djavax.net.debug=ssl

它会打印出.keystore中的一堆东西,所以我确定它正在阅读它。但是当它试图握手时服务器似乎不喜欢它。

如何让SSL Java客户端从我的网络服务器读取数据需要做什么?

-------编辑

哎呀,我刚注意到我正在使用错误的JVM args作为客户端。我改变了这一点,现在似乎进一步发展。

-Djavax.net.ssl.trustStore=.keystore -Djavax.net.ssl.trustStorePassword=changeit

我还没有读过URL数据。我仍然想知道如何给客户端公钥,以便它可以解密而不是整个服务器密钥库。

----------编辑#2

终于搞定了。沿途有几个路障:

出于某种原因,我不得不在Eclipse中创建这样的URL:

URL myurl = new URL("https", host, port, "/docs/setup.html", new sun.net.www.protocol.https.Handler());
HttpsURLConnection con = (HttpsURLConnection)myurl.openConnection();

否则我会在第二行得到一个类强制转换异常。

并且,我必须重新生成我的服务器.keystore文件并使用另一个名称复制到我的客户端:

keytool -genkey -alias tomcat -keyalg RSA -ext san=ip:<my server ip>

我仍然希望更好地了解客户端而不是整个密钥库所需的内容,但至少我现在可以使用它。

1 个答案:

答案 0 :(得分:1)

Java“keystore”文件用于提供两个概念上不同的目的。一个目的是作为密钥存储区,其中存储用于证明机器自身身份的密钥对。另一个目的是充当信任存储,用于存储用于识别信任的其他计算机的信息。

您不应将服务器的密钥库文件复制到客户端,因为正如您所说,它包含服务器的私钥,它包含该私钥,因为该文件是服务器的密钥存储区。相反,您希望创建自己的密钥库文件,该文件充当客户端的信任存储,您要在其中导入服务器的证书,以便客户端知道信任服务器。为此,您从服务器的密钥库导出证书,然后将该证书导入客户端的密钥库文件。

我在这个问题的相关答案中出现了一些更详细的信息:

Secret Key SSL Socket connections in Java