hin*_*dev 19 java ssl web-services cxf sni
我已经使用ApacheCXF(v3.0.4)实现了一个JAX-WS客户端,一切都运行成功,但问题出现在我想使用java 8(jdk1.8.0_25)的安全连接(SSL/TLS)时.
我在log中看到以下异常(-Djavax.net.debug = all):
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
Run Code Online (Sandbox Code Playgroud)
在一个依赖者分析后,我发现问题是由于Java 8没有发送server_name(SNI)但是使用Java 7发送它并且Web服务调用成功.
Java8日志(-Djavax.net.debug = all):缺少"Extension server_name"
[...]
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
***
[...]
Run Code Online (Sandbox Code Playgroud)
Java7日志(-Djavax.net.debug = all)(有效):设置 "Extension server_name"
[...]
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]
***
[...]
Run Code Online (Sandbox Code Playgroud)
据观察,在Java 7中设置了Extension server_name,server_name:[host_name:testeo.hostname.es],然后Web服务调用成功运行.
为什么Java 8没有像Java 7那样设置server_name?它是Java配置问题吗?
小智 13
如上所述,原因与使用setHostnameVerifier()中断SNI(Extension server_name)的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);
}
}
Run Code Online (Sandbox Code Playgroud)
您或底层库(WS lib执行此操作)可能正在使用setHostnameVerifier(..)
java8中存在一个错误,如果使用setHostnameVerifier(..),则不会从客户端执行SNI.
https://bugs.openjdk.java.net/browse/JDK-8072464