扩展服务器名称(SNI扩展)不与jdk1.8.0一起发送,但使用jdk1.7.0发送
我已经使用ApacheCXF(v3.0.4)实现了一个JAX-WS客户端,并且一切正常,但问题出现在我想要使用与java 8(jdk1.8.0_25)的安全连接(SSL/TLS)。扩展服务器名称(SNI扩展)不与jdk1.8.0一起发送,但使用jdk1.7.0发送
我看到在日志中出现以下异常(-Djavax.net.debug =全部):
main, handling exception: java.net.SocketException: Connection reset
main, SEND TLSv1.2 ALERT: fatal, description = unexpected_message
main, WRITE: TLSv1.2 Alert, length = 2
main, Exception sending alert: java.net.SocketException: Connection reset by peer: socket write error
后,我已经注意到了此问题,是因为引起了depeer分析与Java 8中的服务器名(SNI)不发送,但使用Java 7发送并且Web服务调用成功运行。
的Java 8日志(-Djavax.net.debug =全部):缺少 “扩展服务器名”
[...]
Compression Methods: { 0 }
Extension elliptic_curves, curve names: {secp256r1, sect163k1, sect163r2, secp192r1, secp224r1, sect233k1, sect233r1, sect283k1, sect283r1, secp384r1, sect409k1, sect409r1, secp521r1, sect571k1, sect571r1, secp160k1, secp160r1, secp160r2, sect163r1, secp192k1, sect193r1, sect193r2, secp224k1, sect239k1, secp256k1}
Extension ec_point_formats, formats: [uncompressed]
Extension signature_algorithms, signature_algorithms: SHA512withECDSA, SHA512withRSA, SHA384withECDSA, SHA384withRSA, SHA256withECDSA, SHA256withRSA, SHA224withECDSA, SHA224withRSA, SHA1withECDSA, SHA1withRSA, SHA1withDSA, MD5withRSA
***
[...]
Java 7的日志(-Djavax.net.debug =全部)(作品): “扩展服务器名” 被设置
[...]
Compression Methods: { 0 }
Extension elliptic_curves, curve names: {secp256r1, sect163k1, sect163r2, secp192r1, secp224r1, sect233k1, sect233r1, sect283k1, sect283r1, secp384r1, sect409k1, sect409r1, secp521r1, sect571k1, sect571r1, secp160k1, secp160r1, secp160r2, sect163r1, secp192k1, sect193r1, sect193r2, secp224k1, sect239k1, secp256k1}
Extension ec_point_formats, formats: [uncompressed]
Extension signature_algorithms, signature_algorithms: SHA512withECDSA, SHA512withRSA, SHA384withECDSA, SHA384withRSA, SHA256withECDSA, SHA256withRSA, SHA224withECDSA, SHA224withRSA, SHA1withECDSA, SHA1withRSA, SHA1withDSA, MD5withRSA
Extension server_name, server_name: [host_name: testeo.hostname.es]
***
[...]
据观察,与Java 7 扩展服务器名,服务器名:[HOST_NAME:testeo.hostname.es]被设置,然后将带状片S服务调用成功。
为什么Java 8没有像Java 7那样设置server_name?它是一个Java配置问题?
你,或底层库(的WS LIB做的话)可能是使用setHostnameVerifier( ..)
在java8中有一个错误,如果使用setHostnameVerifier(..),则SNI不是从客户端完成的。
如前所述,原因是在哪里使用setHostnameVerifier()打破SNI(扩展服务器名)相关的JDK错误。 https://bugs.openjdk.java.net/browse/JDK-8144566
我们的解决方法: 经过测试我们发现,设置连接的SSLSocketFactory的只是关于从默认的东西似乎解决这个问题。
这不起作用: HttpsURLConnection.setSSLSocketFactory((SSLSocketFactory) SSLSocketFactory.getDefault());
这并不工作: HttpsURLConnection.setSSLSocketFactory(new SSLSocketFactoryFacade());
因此,要解决它的一个JAX-WS客户端,你可以做这样的事情: bindingProvider.getRequestContext().put("com.sun.xml.internal.ws.transport.https.client.SSLSocketFactory", new SSLSocketFactoryFacade());
我们的SSLSocketFactory正面:(请注意它确实没有任何作用)
public class SSLSocketFactoryFacade extends SSLSocketFactory {
SSLSocketFactory sslsf;
public SSLSocketFactoryFacade() {
sslsf = (SSLSocketFactory) SSLSocketFactory.getDefault();;
}
@Override
public String[] getDefaultCipherSuites() {
return sslsf.getDefaultCipherSuites();
}
@Override
public String[] getSupportedCipherSuites() {
return sslsf.getSupportedCipherSuites();
}
@Override
public Socket createSocket(Socket socket, String s, int i, boolean b) throws IOException {
return sslsf.createSocket(socket, s, i, b);
}
@Override
public Socket createSocket(String s, int i) throws IOException, UnknownHostException {
return sslsf.createSocket(s, i);
}
@Override
public Socket createSocket(String s, int i, InetAddress inetAddress, int i1) throws IOException, UnknownHostException {
return sslsf.createSocket(s, i, inetAddress, i1);
}
@Override
public Socket createSocket(InetAddress inetAddress, int i) throws IOException {
return createSocket(inetAddress, i);
}
@Override
public Socket createSocket(InetAddress inetAddress, int i, InetAddress inetAddress1, int i1) throws IOException {
return createSocket(inetAddress, i, inetAddress1, i1);
}
}
请解释什么是绑定提供程序和/或添加代码来演示我想用你的解决方案来修复现有系统中的这个bug – chrisinmtown
这个门面类的技巧和我自定义的HostnameVerifier一起修复了我的应用程序在JDK8中。 – Whome
我有个例外:每当我重新启动PC并用客户端应用程序启动Tomcat时,“BuilderException:无法找到有效的请求目标的证书路径”。重新启动Tomcat后,一切正常。插入日志中,我发现由于某种原因,扩展server_name在第一次运行期间不在ClientHello中。自定义SSLSocketFactoryFacade解决了这个问题。 BTW Lombok的@Delegate注释将使这个类超小。 – Yuriy
欢迎来到Stack Overflow!与论坛网站不同,我们不使用“谢谢”或“任何帮助表示赞赏”,或在[so]上签名。请参阅“[应该'嗨','谢谢',标语和致敬从帖子中删除?](http://meta.stackexchange.com/questions/2950/should-hi-thanks-taglines-and-salutations-be ),这是“预先感谢”,而不是“感谢先进” –