【问题标题】:SSLHandshakeException while connecting to HTTPS from java code从 Java 代码连接到 HTTPS 时出现 SSLHandshakeException
【发布时间】:2015-06-05 16:21:48
【问题描述】:

我们在旧版应用程序的开发环境中拥有自签名证书。可以从浏览器访问应用程序(出现证书错误 - 此 CA 根证书不受信任,因为它不在受信任的根证书颁发机构存储中。)但是当从 java 代码访问时(使用 HttpsURLConnection),它会给出 SSLHandshakeException。

在浏览了许多 stackoverflow 问题(包括telling java to accept self-signed ssl certificate)和互联网上的一些文章后,我按照以下步骤操作,但还没有运气:

  1. 从浏览器中导出的证书 (mycert.cer)
  2. 使用以下命令在 JVM 信任库中导入了这个 mycert.cer: keytool -import -alias myApp -file mycert.cer -keystore cacerts -storepass changeit

运行后,检查是否成功添加 keytool -list -keystore cacerts

即使在 java 信任库中添加了这个证书,来自 java 代码的 https 给了我 javax.net.ssl.SSLHandshakeException:收到致命警报:handshake_failure

非常感谢任何关于此的指针。

请注意:这个自签名证书是很久以前创建的,我们没有太多关于它是如何创建的详细信息。

更多细节: Java 版本 - Java 1.6 完整的错误跟踪:

javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
    at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:174)
    at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:136)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:1822)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1004)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1188)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1215)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1199)
    at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:434)
    at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:166)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1195)
    at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:379)
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:318)

javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
    at sun.net.www.protocol.http.HttpURLConnection$6.run(HttpURLConnection.java:1514)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.net.www.protocol.http.HttpURLConnection.getChainedException(HttpURLConnection.java:1508)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1162)
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:234)

Caused by: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
    at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:174)
    at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:136)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:1822)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1004)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1188)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1215)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1199)
    at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:434)
    at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:166)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1195)
    at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:379)
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:318)

    ... 1 more

【问题讨论】:

  • 握手异常可以是任何东西,例如协议版本不匹配、密码...请提供调试输出、数据包捕获、有关使用的 Java 版本的信息等。
  • 嗨 Steffen,我是 SSL 新手,请告诉我如何找到数据包捕获? java版本是1.6

标签: java ssl https ssl-certificate keytool


【解决方案1】:

如果您发布 SSLHandshakeException 堆栈跟踪会更好。但是,如果你得到这样的东西:

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException:PKIX 路径构建失败: sun.security.provider.certpath.SunCertPathBuilderException:无法 找到请求目标的有效认证路径

那么请查看以下网址。这些将很有用:

一个。 http://www.mkyong.com/webservices/jax-ws/suncertpathbuilderexception-unable-to-find-valid-certification-path-to-requested-target/

b. http://code.google.com/p/java-use-examples/source/browse/trunk/src/com/aw/ad/util/InstallCert.java

如果你得到这样的东西:

javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException:没有主题替代名称 现在

在创建密钥库时使用-ext san=ip:<IP Address>, san(主题备用名称)。从 JDK 1.7 开始支持此功能。

【讨论】:

  • 感谢 Somnath 分享详细信息。我的客户端应用程序(使用我的应用程序的 api)报告 - javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX 路径构建失败。当我在本地尝试通过创建一个访问我的 https url 的 java 应用程序来重现这一点时,我得到“javax.net.ssl.SSLHandshakeException:收到致命警报:handshake_failure”(我的问题中的跟踪)。我尝试按照您提供的 mkyonk 示例的步骤操作,但出现错误 - “无法获取服务器证书链”
【解决方案2】:

您最好的选择可能是获取 wireshark 并验证 SSL 警报值,然后从那里开始。这可能是警报值 40,这意味着您没有找到兼容的协议。服务器需要客户端不支持的 SSL/TLS 版本,或者它们没有兼容的密码套件。

【讨论】:

  • 你也可以在java javax.net.debug=all中开启ssl调试。
猜你喜欢
  • 2023-03-03
  • 2016-07-12
  • 2017-10-24
  • 2015-12-11
  • 1970-01-01
  • 2012-04-16
  • 2018-03-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多