我正在使用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
我甚至不确定客户端证书是否存在问题 .
8 回答
使用下面的代码
要么
根本不需要 . 此外,您无需创建自己的自定义SSL工厂 .
我也遇到了同样的问题,在我的情况下,有一个问题是 complete certificate chain 没有导入到信任库 . 使用keytool实用程序右边的根证书导入证书,也可以在记事本中打开cacerts文件,看看是否导入了完整的证书链 . 检查导入证书时提供的别名,打开证书并查看其中包含的别名,cacerts文件中应该有相同数量的证书 .
还应在运行应用程序的服务器中配置cacerts文件,这两个服务器将使用公钥/私钥进行相互身份验证 .
终于解决了;) . 得到了强烈的暗示here(Gandalfs的回答也有点触及) . 丢失的链接(大部分)是下面的第一个参数,在某种程度上,我忽略了密钥库和信任商店之间的区别 .
必须将自签名服务器证书导入信任库:
需要设置这些属性(在命令行或代码中):
工作示例代码:
虽然不推荐,但您也可以完全禁用SSL证书验证:
您是否设置了KeyStore和/或TrustStore系统属性?
或者来自代码
与javax.net.ssl.trustStore相同
如果您正在使用Axis框架处理Web服务调用,则有一个更简单的答案 . 如果您希望客户能够调用SSL Web服务并忽略SSL证书错误,那么只需在调用任何Web服务之前放置此语句:
System.setProperty("axis.socketSecureFactory", "org.apache.axis.components.net.SunFakeTrustSocketFactory");
通常的免责声明适用于在 生产环境 环境中做的非常糟糕的事情 .
我在the Axis wiki找到了这个 .
对我来说,这是使用Apache HttpComponents~HttpClient 4.x的方法:
P12文件包含使用BouncyCastle创建的客户端证书和客户端私钥:
我使用Apache commons HTTP Client包在我当前的项目中执行此操作,并且它可以正常使用SSL和自签名证书(在将其安装到您提到的cacerts之后) . 请看这里:
http://hc.apache.org/httpclient-3.x/tutorial.html
http://hc.apache.org/httpclient-3.x/sslguide.html
我认为你的服务器证书有问题,不是有效的证书(我认为这是“handshake_failure”在这种情况下的含义):
将服务器证书导入客户端JRE上的trustcacerts密钥库 . 这很容易用keytool完成: