java – 扩展server_name(SNI扩展名)不是用jdk1.8.0发送的,而是用jdk1.7.0发送的

前端之家收集整理的这篇文章主要介绍了java – 扩展server_name(SNI扩展名)不是用jdk1.8.0发送的,而是用jdk1.7.0发送的前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我已经通过使用ApacheCXF(v3.0.4)实现了一个JAX-WS客户端,并且一切正常工作,但是当我想要使用安全连接(SSL / TLS)与 java 8(jdk1.8.0_25)时出现问题.

我在日志中看到以下异常(-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配置问题吗?

解决方法

如上所述,原因与使用setHostnameVerifier()的JDK错误与SNI(Extension server_name)相关.
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);
    }
}
原文链接:https://www.f2er.com/java/121219.html

猜你在找的Java相关文章