连接到https站点时发生SSLHandshakeException
问题内容:
我正在尝试通过jmeter(版本2.13,java版本-1.8u31)记录一个https
站点,并且在连接到https站点时出现SSLHandshakeException。错误消息是
javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.Alerts.getSSLException(Alerts.java:154)
at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:2011)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1113)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1363)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1391)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1375)
at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:436)
at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:180)
at org.apache.http.impl.conn.ManagedClientConnectionImpl.open(ManagedClientConnectionImpl.java:294)
at org.apache.jmeter.protocol.http.sampler.MeasuringConnectionManager$MeasuredConnection.open(MeasuringConnectionManager.java:107)
at org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:643)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:479)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:906)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:805)
at org.apache.jmeter.protocol.http.sampler.HTTPHC4Impl.executeRequest(HTTPHC4Impl.java:517)
at org.apache.jmeter.protocol.http.sampler.HTTPHC4Impl.sample(HTTPHC4Impl.java:331)
at org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy.sample(HTTPSamplerProxy.java:74)
at org.apache.jmeter.protocol.http.sampler.HTTPSamplerBase.sample(HTTPSamplerBase.java:1146)
at org.apache.jmeter.protocol.http.proxy.Proxy.run(Proxy.java:240)
我已经打开了SSL的调试日志记录,但是我无法理解根本原因。看来,Java客户端发送客户问候,但没有收到的服务器问候消息(其中服务器选择SSL的最高版本,最好的加密套件,无论是客户端和服务器支持,并将该信息发送给客户端)。我看到客户端发送,读取和接收的协议版本之间的差异(TLSv1.1与TLSv1.2)
这是根本原因吗?如果是这样,我该如何解决?
日志粘贴在此处-Java SSLHandshakeException日志-
Pastebin.com
更新资料
正如@Anand
Bhatt所建议的那样,我使用ssllabs分析了该网站,并了解了以下内容
- 服务器不支持Java 8支持的TLSv1.2
- 该服务器仅支持一个密码套件-TLS_RSA_WITH_AES_256_CBC_SHA
- Java 8u31不支持服务器支持的密码套件,这很可能是问题所在。
听起来对吗?如果是这样,我们如何使Java 8客户端支持服务器支持的密码套件?
问题答案:
SSLlabs显然正在测试“开箱即用”的支持。Java加密技术可以追溯到1990年代,当时美国政府严格限制了加密软件的出口,因此 ,当时的Sun发行
了JRE(或JDK) ,Sun现在开始了。Oracle 不允许使用 256位
对称加密,这是您的服务器要求的。您必须为您的Java(主要)版本下载并安装“ JCE无限强度
管辖权策略文件”;图8在http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html上。文件中的README提供了冗长的细节,但是基本上您可以在JRE
/ lib / security中替换两个小jar文件。
TLSv1.2工作 是不是一个真正的问题 现在 。TLS协议自动协商两端支持(和启用)的最高版本。Java 8 实现了
SSLv3,TLSv1.0,TLSv1.1和TLSv1.2,但是由于POODLE的缘故, 默认情况下 ,最近的更新(8u31或7u75及更高版本)
默认 禁用 SSLv3 。您可以根据需要重新启用它,但是您不愿意这样做。(Java 7实现了相同的协议版本,但是默认情况下,由于禁用兼容性,
客户端 默认禁用1.1和1.2。)
但是,由于POODLE和BEAST,一些安全性机构不再接受SSLv3和TLSv1.0的足够安全性。一个重要的示例是信用卡和借记卡,如https://security.stackexchange.com/a/87077/39571中所述。TLSv1.2包含了超过1.1的一些技术改进,使其成为当今的
首选 ,并且可能会有未来的发现使这些改进变得至关重要。如果您的服务器 当时 不支持1.2(甚至更高) ,
您将会遇到麻烦。类似地,服务器唯一支持的套件使用纯RSA密钥交换(即非前向保密性)的事实现在被认为不是最佳的,随着时间的流逝,它可能会变得不可接受。
keytool (至少与通常使用的密钥库和信任库文件有关)与对称密码无关。如果服务器使用您的JRE和/或应用程序不信任的 CA根目录
(或更确切地说,更一般地说是信任锚),并且/或者服务器希望使用 SSL / TLS级别的 客户端身份验证
,则可能是相关的这是相当罕见的。(至少在Web应用程序级别大多数网站身份验证,或HTTP水平,如果在所有。)SSLLabs服务器证书链(和一些其他的东西也可以)的检查一般是严格比Java的,他们并没有抱怨
那 区域,因此不太可能在那里出现问题。