我在日志中看到以下异常(-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
经过depeer分析后,我观察到问题是由于使用Java 8而不是发送服务器名称(SNI),而是使用Java 7发送该问题,并且Web服务调用成功工作.
Java 8 log(-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 *** [...]
Java 7 log(-Djavax.net.debug = all)(works):“扩展名server_name”被设置
[...] Compression Methods: { 0 } Extension elliptic_curves,MD5withRSA Extension server_name,server_name: [host_name: testeo.hostname.es] *** [...]
观察到使用Java 7,扩展名server_name,server_name:[host_name:testeo.hostname.es]被设置,然后Web服务调用成功工作.
Java 7为什么没有将server_name设置为Java 7?是Java配置问题吗?
解决方法
https://bugs.openjdk.java.net/browse/JDK-8144566
我们的解决方法:
测试后,我们发现将连接的SSLSocketFactory设置为与默认值相似的任何内容似乎可以解决问题.
这不行:
HttpsURLConnection.setSSLSocketFactory((SSLSocketFactory)SSLSocketFactory.getDefault());
这样做有效:
HttpsURLConnection.setSSLSocketFactory(new SSLSocketFactoryFacade());
所以,要修复一个JAX-WS客户端,你可以这样做:
bindProvider.getRequestContext().put(“com.sun.xml.internal.ws.transport.https.client.SSLSocketFactory”,新的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,InetAddress inetAddress,int i1) throws IOException,inetAddress,i1); } @Override public Socket createSocket(InetAddress inetAddress,int i) throws IOException { return createSocket(inetAddress,i); } @Override public Socket createSocket(InetAddress inetAddress,InetAddress inetAddress1,int i1) throws IOException { return createSocket(inetAddress,inetAddress1,i1); } }