我正在使用Java 6,并尝试使用客户端证书针对远程服务器创建HttpsURLConnection
。
服务器使用的是自签名的根证书,并且要求提供一个受密码保护的客户端证书。我已经将服务器根证书和客户端证书添加到我在/System/Library/Frameworks/JavaVM.framework/Versions/1.6.0/Home/lib/security/cacerts
(OSX 10.5)中找到的默认java密钥库中。密钥库文件的名称似乎表明客户端证书不应该放在那里?
无论如何,将根证书添加到此存储解决了臭名昭著的javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed' problem.
问题。
然而,我现在被如何使用客户端证书所困,我尝试了两种方法,但都没有得到任何结果。
首先,也是首选,尝试:
SSLSocketFactory sslsocketfactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
URL url = new URL("https://somehost.dk:3049");
HttpsURLConnection conn = (HttpsURLConnection)url.openConnection();
conn.setSSLSocketFactory(sslsocketfactory);
InputStream inputstream = conn.getInputStream();
// The last line fails, and gives:
// javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
我试过跳过HttpSURLConnection类(不理想,因为我想与服务器进行HTTP对话),并改为这样做:
SSLSocketFactory sslsocketfactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
SSLSocket sslsocket = (SSLSocket) sslsocketfactory.createSocket("somehost.dk", 3049);
InputStream inputstream = sslsocket.getInputStream();
// do anything with the inputstream results in:
// java.net.SocketTimeoutException: Read timed out
我甚至不确定客户端证书是否是这里的问题。
9条答案
按热度按时间qxsslcnc1#
我使用Apache commons HTTP Client包在我当前的项目中完成此操作,它可以很好地使用SSL和自签名证书(在安装到您提到的cacerts之后)。请在这里查看:
http://hc.apache.org/httpclient-3.x/tutorial.html
http://hc.apache.org/httpclient-3.x/sslguide.html
ewm0tg9j2#
我认为你的服务器证书有问题,不是一个有效的证书(我认为这就是“handshake_failure”在这种情况下的意思):
将您的服务器证书导入到客户端JRE上的trustcacerts密钥库中。这可以通过keytool轻松完成:
ymzxtsji3#
使用以下代码
或
也不需要创建自己的自定义SSL工厂。
我也遇到了同样的问题,在我的案例中有一个问题,即完整的证书链没有导入到信任库中。使用keytool实用程序从根证书导入证书,也可以在记事本中打开cacerts文件,看看是否导入了完整的证书链。检查导入证书时提供的别名,打开证书,看看它包含多少证书,cacerts文件中应该有相同数量的证书。
此外,应该在运行应用程序的服务器中配置cacerts文件,这两个服务器将使用公钥/私钥相互验证。
gzszwxb44#
虽然这个问题已经有12年多的历史了,并且有很多很好的答案,但我想提供一个替代方案。下面是加载keystore和truststore并获取sslsocketfactory或sslcontext的一小段代码:
此示例代码片段来自库:GitHub - SSLContext Kickstart您可以使用以下代码段添加它:
c7rzv4ha5#
终于解决了;得到了一个强烈的提示here(甘道夫的回答也触及了一点)。丢失的链接(大部分)是下面的第一个参数,在某种程度上,我忽略了密钥库和信任库之间的区别。
必须将自签名服务器证书导入到信任库中:
keytool -import -alias gridserver -file gridserver.crt -storepass $PASS -keystore gridserver.keystore
需要设置以下属性(在命令行或代码中):
工作示例代码:
yv5phkfx6#
虽然不推荐,但您也可以使用来自The Java Developers Almanac的以下代码完全禁用SSL证书验证:
1rhkuytd7#
是否设置了KeyStore和/或TrustStore系统属性?
或从代码
与javax .NET.ssl.trustStore相同
iszxjhcz8#
如果您正在使用Axis框架处理Web服务调用,则有一个更简单的答案。如果您的客户端希望能够调用SSL Web服务并忽略SSL证书错误,只需在调用任何Web服务之前添加以下语句:
System.setProperty("axis.socketSecureFactory", "org.apache.axis.components.net.SunFakeTrustSocketFactory");
在生产环境中,这是一件非常糟糕的事情,这是常见的声明。
我在the Axis wiki找到了这个。
zvms9eto9#
对我来说,这就是使用Apache HttpComponents ~ HttpClient 4.x的工作原理:
P12文件包含使用BouncyCastle创建的客户端证书和客户端私钥: