He implementado un JAX-WS cliente mediante el uso de ApacheCXF (v3.0.4) y todo funciona correctamente pero el problema viene cuando quiero usar una conexión segura (SSL/TLS) con java 8 (jdk1.8.0_25).

Veo de la siguiente excepción en el registro (-Djavax.net.debug=todos):

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

Después de un depeer análisis que he observado que el problema es causado porque el con Java 8 server_name (SNI) no se envía, pero con Java 7 es enviado y la invocación de servicios web funciona correctamente.

Java 8 log (-Djavax.net.debug=todos): Falta «Extensión 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=todos) (obras): «Extensión server_name» es el conjunto de

[...]
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]
***
[...]

Se observa que con Java 7 el Extensión server_name, server_name: [host_name: testeo.nombre de host.es] es el conjunto y, a continuación, la invocación de servicios web funciona correctamente.

¿Por qué no Java 8 ajuste de la server_name como Java 7 ¿? Es una configuración de Java problema?

InformationsquelleAutor hints4dev | 2015-06-13

5 Comentarios

  1. 13

    Como se ha mencionado, la causa está relacionada con el JDK bug donde el uso de setHostnameVerifier() rompe SNI (Extensión server_name).
    https://bugs.openjdk.java.net/browse/JDK-8144566

    Nuestra solución:
    Después de las pruebas se encontró que la configuración de una conexión SSLSocketFactory a apenas sobre cualquier cosa, desde el valor predeterminado parece solucionar el problema.

    Esto no funciona:
    HttpsURLConnection.setSSLSocketFactory((SSLSocketFactory) SSLSocketFactory.getDefault());

    Esto funciona:
    HttpsURLConnection.setSSLSocketFactory(new SSLSocketFactoryFacade());

    Así, para que la arregle por un JAX-WS cliente, usted podría hacer algo como esto:
    bindingProvider.getRequestContext().put("com.sun.xml.internal.ws.transport.https.client.SSLSocketFactory", new SSLSocketFactoryFacade());

    Nuestro SSLSocketFactory fachada: (Nota que realmente no hacer nada)

    • Por favor explique lo que es un bindingProvider y/o agregar código para demostrar. Me gustaría usar la solución para tratar de solucionar este error en un sistema existente.
    • La fachada esta clase de truco fijo mi aplicación en JDK8 junto con la medida de HostnameVerifier. Sin una fachada truco yo no era capaz de usar un verificador.
    • Tuve excepción: «BuilderException: no se puede encontrar la ruta de certificación válida para el destino solicitado» cada vez que he reiniciado el PC y empezó a Tomcat con la aplicación cliente. Después de reiniciar Tomcat todo lo trabajado. Después de mirar en los logs me enteré de que, por alguna razón, la Extensión de server_name no estaba presente en el ClientHello durante la primera ejecución. La costumbre SSLSocketFactoryFacade solucionado el problema. BTW Lombok @Delegado de anotación va a hacer que la clase super pequeño.
    • Puede usted explicar cómo se solucionó el problema? si la fachada no hace nada, es que hay algo, que se basa en el nombre de la clase?
  2. 0

    Primero de todo, este «server_name» cosas es asociado con el SNI (Server Name Indication) de extensión. El Java 8 JSSE la documentación habla de aquí.

    La documentación incluye código de ejemplo que muestra cómo configurar el servidor de nombres que se envían. El código es para Java 8.

    Sin embargo, no puedo entender por qué (al parecer) de Java 7 es configurar el nombre del servidor por defecto, y Java 8 no. (La manera más fácil de averiguarlo sería el uso de un depurador de averiguar cómo el SSL motor de objeto es creado e inicializado.)

    • Me he encontrado con problema similar con java7 no se ajusta en algunos casos, y el establecimiento en los demás.
  3. 0

    He probado la solución proporcionada por Benjamin Parry, pero no me funciona. Después de algunos excavación alrededor, también encontré esta solución que parece muy similar, sin embargo la SSLSocketFactoryFacade manualmente inserta el correcto SSL encabezado en lugar de ser un puro pasar-aunque. Para aportar mi código final por debajo de la cual es ligeramente diferente, pero que se pueda dar crédito a Girish Kamath en javabreaks para la idea básica:

        private static class SSLSocketFactoryFacade extends SSLSocketFactory {
    private SSLSocketFactory sslsf;
    private SSLParameters sslParameters;
    public SSLSocketFactoryFacade(String hostName) {
    sslParameters = new SSLParameters();
    sslParameters.setServerNames(Arrays.asList(new SNIHostName(hostName)));
    sslsf = (SSLSocketFactory) SSLSocketFactory.getDefault();;
    }
    public Socket createSocket() throws IOException {
    Socket socket = sslsf.createSocket();
    ((SSLSocket) socket).setSSLParameters(sslParameters);
    return socket;
    }
    public Socket createSocket(InetAddress arg0, int arg1, InetAddress arg2, int arg3) throws IOException {
    Socket socket = sslsf.createSocket(arg0, arg1, arg2, arg3);
    ((SSLSocket) socket).setSSLParameters(sslParameters);
    return socket;
    }
    public Socket createSocket(InetAddress arg0, int arg1) throws IOException {
    Socket socket = sslsf.createSocket(arg0, arg1);
    ((SSLSocket) socket).setSSLParameters(sslParameters);
    return socket;
    }
    public Socket createSocket(Socket arg0, InputStream arg1, boolean arg2) throws IOException {
    Socket socket = sslsf.createSocket(arg0, arg1, arg2);
    ((SSLSocket) socket).setSSLParameters(sslParameters);
    return socket;
    }
    public Socket createSocket(Socket arg0, String arg1, int arg2, boolean arg3) throws IOException {
    Socket socket = sslsf.createSocket(arg0, arg1, arg2, arg3);
    ((SSLSocket) socket).setSSLParameters(sslParameters);
    return socket;
    }
    public Socket createSocket(String arg0, int arg1, InetAddress arg2, int arg3)
    throws IOException, UnknownHostException {
    Socket socket = sslsf.createSocket(arg0, arg1, arg2, arg3);
    ((SSLSocket) socket).setSSLParameters(sslParameters);
    return socket;
    }
    public Socket createSocket(String arg0, int arg1) throws IOException, UnknownHostException {
    Socket socket = sslsf.createSocket(arg0, arg1);
    ((SSLSocket) socket).setSSLParameters(sslParameters);
    return socket;
    }
    public String[] getDefaultCipherSuites() {
    return sslsf.getDefaultCipherSuites();
    }
    public String[] getSupportedCipherSuites() {
    return sslsf.getSupportedCipherSuites();
    }
    }

    Y, a continuación, me pueden llamar

    sslConnection.setSSLSocketFactory(new SSLSocketFactoryFacade(sslConnection.getURL().getHost()));

    donde sslConnection es el HttpsURLConnection.

Dejar respuesta

Please enter your comment!
Please enter your name here