2015-09-11 12 views
8

un client creato con Apache CXF che funzionava correttamente, utilizzando un determinato server (ad esempio: https://serverexample.com/application/webservice?wsdl).Errore client Apache CXF nel server di test che necessita dell'indicazione SNI (Server Name Indication)

ma il server si è spostato in un altro IP, e ora ha due certificati SSL con TLS e SNI (Server Name Indication) nello stesso IP, e ora le nostre applicazioni non riesce con questo errore:

javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No subject alternative DNS name matching serverexample.com found 

Capisco che questo si verifica quando https sta ottenendo il certificato sbagliato (ha un altro nome di server), e quindi non corrisponde alla mia.

ho cercato di scoprire cosa succede con OpenSSL, e l'URL funziona solo se ho messo servername:

# openssl s_client -connect serverexample.com:443 -tls1 
Certificate chain 
0 s:/CN=otherserver.com/OU=Servers/O=MyOrganization/C=ES 
    i:/CN=ACV20/OU=PKACV/O=ACV/C=ES 

# openssl s_client -connect serverexample.com:443 -servername serverexample.com 
Certificate chain 
0 s:/CN=serverexample.com/OU=Servers/O=MyOrganization/C=ES 
    i:/CN=ACV220/OU=PKACV1/O=ACV2/C=ES 

L'errore è accaduto nel client apache generato in questo punto:

final URL wsdlURL = new URL("https://serverexample.com/application/webservice?wsdl"); 
final Operation_Service ss = new Operation_Service(wsdlURL, SERVICE_NAME); 

Non riesce nel nuovo Operation_Service:

@WebServiceClient(name = "ENI.Operation", 
        wsdlLocation = "https://serverexample.com/application/webservice?wsdl", 
        targetNamespace = "http://inter.ra.es/awrp/wsdl") 
public class Operation_Service extends Service { 
    public final static URL WSDL_LOCATION; 
    public final static QName SERVICE = new QName("http://inter.ra.es/awrp/wsdl", "ENI.Operation"); 
    public final static QName Operation = new QName("http://inter.ra.es/awrp/wsdl", "ENI.Operation"); 
    static { 
     URL url = null; 
     try { 
      url = new URL("https://serverexample.com/application/webservice?wsdl"); 
     } catch (final MalformedURLException e) { 
      java.util.logging.Logger.getLogger(Operation_Service.class.getName()) 
       .log(java.util.logging.Level.INFO, 
        "Can not initialize the default wsdl from {0}", "https://serverexample.com/application/webservice?wsdl"); 
     } 
     WSDL_LOCATION = url; 
    } 

    public Operation_Service(final URL wsdlLocation, final QName serviceName) { 
     super(wsdlLocation, serviceName); 
    } 

javax.xml.ws.Service chiamate javax.xml.ws .spi.ServiceDelegate, una classe di abstract implementata da qualche classe in org.apache.cxf.jaxws .. ma qui sto perdendo, non so cosa guardare ...

Il nostro cliente è runnring in java 7.0 con apache cxf 3.0.4 su un weblogic 12.1.1.0. Ho letto che in Java 6 c'erano problemi con SNI, ma stiamo usando 7.0 qui.

Non so cosa posso fare. C'è qualche opzione in java o nel nostro client per indicare il nomeserver (come in openssl) che stiamo cercando di connettere?

risposta

4

È una combinazione di "miglioramenti" in JDK 1.8 e il fatto che il server ha diversi certificati.

Ciò che è rotto in JDK 1.8 è spiegata qui: http://lea-ka.blogspot.com/2015/09/wtf-collection-how-not-to-add-api.html

Va in questo modo:

  • estensione No SNI viene inviato a causa di bug https://bugs.openjdk.java.net/browse/JDK-8072464.
  • Il server restituisce il certificato "CN = otherserver.com", che probabilmente ha anche SAN (SubjectAlternativeName) "otherserver.com" e nessun altro.
  • I controlli di "spoofing URL" in JDK predefiniti sono perofrmed e confrontare "serverexample.com" dall'URL e "otherserver.com" dal certificato. Ooops, ottieni la tua eccezione.

Il più semplice correzione è quello di scaricare tutti i file WSDL e XSD e li pacchetto da qualche parte nel vostro vaso.

Se davvero bisogno per andare a prendere il WSDL dal server remoto, questo potrebbe aiutare:

finale WSDLURL URL = new URL ("https: // otherserver.com/application/webservice WSDL ");

Ma questo potrebbe non funzionare perché "/ applicazione/webservice" potrebbe essere nota solo a serverexample.com. In questo caso si ottiene la connessione TLS e quindi il codice di risposta HTTP 404.

Se questo non funziona dovrete ricorrere a tutti i tipi di fabbriche SSL (che è verboso ma sicuramente possibile) e tenta di collegarli a classi javax.ws .... (che dovrebbe essere possibile ma ho mai fatto quella parte).

+0

Dubito che sia dovuto a JDK-8072464 poiché il verificatore del nome host predefinito non sembra essere modificato. Forse è l'altro bug che lo fa fallire anche quando viene impostato un algoritmo di identificazione degli endpoint. Sono alcuni esempi su come lavorarlo con le fabbriche personalizzate, ma non per il caso CXF. – jmd

+0

Certo, il verificatore non è stato modificato. Ma un altro codice vede che il verificatore del nome host è presente e si comporta diversamente. È tutto spiegato nel post collegato. – user568826

0

auguriamo che questo utile per voi:

per risolvere eccezione handshake SSL è possibile scegliere 2 modi: impostare questa proprietà sistema all'inizio del tuo codice:

System.setProperty("jsse.enableSNIExtension", "false");

o

imposta l'argomento VM per il tuo programma come: -Djsse.enableSNIExtension=false

+0

No, questa non è la risposta. Qui * vogliamo * il client per inviare l'estensione SNI e Java non a causa di un bug. – jmd

Problemi correlati