2012-01-28 8 views
6

Devo chiamare un servizio WCF protetto da java utilizzando l'autenticazione reciproca. Tutto funziona correttamente, tranne che non riesco a inviare messaggi con dimensioni superiori a 48680 byte. Quindi i messaggi di 48680 byte vengono inviati correttamente, ma 48681 byte - non lo sono, e l'applicazione java ha esito negativo con un'eccezione di timeout di lettura, sebbene le impostazioni delle quote di WCF consentano messaggi molto più grandi.Impossibile inviare un messaggio 48681 byte per proteggere il servizio wcf da java

Quindi quale potrebbe essere il problema?


EDIT

Il codice sorgente:

package foo.bar; 

import org.apache.commons.io.FileUtils; 
import org.apache.commons.io.IOUtils; 
import org.junit.Test; 

import javax.net.ssl.*; 
import java.io.*; 
import java.net.URL; 
import java.security.KeyStore; 

public class ReadTimedOutTest { 

    @Test 
    public void testReadTimedOut() throws Exception { 
     URL url = new URL("https://services/endpoint/"); 

     HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); 
     setUpSSL(connection); 
     connection.setDoOutput(true); 
     connection.setDoInput(true); 
     connection.setRequestMethod("POST"); 
     connection.setRequestProperty("SOAPAction", "http://namespace/2012/01/service/Operation"); 
     connection.setRequestProperty("Accept", "*/*"); 
     connection.setRequestProperty("Connection", "Keep-Alive"); 
     connection.setRequestProperty("Content-Type", "text/xml; charset=utf-8"); 

     connection.setConnectTimeout(10 * 1000); 
     connection.setReadTimeout(10 * 1000); 
     connection.setInstanceFollowRedirects(true); 

     ByteArrayOutputStream bos = new ByteArrayOutputStream(); 
     InputStream is = ReadTimedOutTest.class.getResourceAsStream("payload.failure.xml"); 
     try { 
      IOUtils.copy(is, bos); 
     } finally { 
      is.close(); 
     } 
     byte[] bytes = bos.toByteArray(); 
     connection.setRequestProperty("Content-Length", String.valueOf(bytes.length)); 

     OutputStream os = connection.getOutputStream(); 
     try { 
      IOUtils.copy(new ByteArrayInputStream(bytes), os); 
      os.flush(); 
     } finally { 
      os.close(); 
     } 

     int respCode = connection.getResponseCode(); 
     if(respCode >= HttpsURLConnection.HTTP_INTERNAL_ERROR) { 
      is = connection.getErrorStream(); 
      try { 
       IOUtils.copy(is, System.err); 
      } finally { 
       is.close(); 
      } 
     } else { 
      is = connection.getInputStream(); 
      try { 
       IOUtils.copy(is, System.out); 
      } finally { 
       is.close(); 
      } 
     } 
    } 

    private void setUpSSL(HttpsURLConnection connection) throws Exception { 
     byte[] bytes = FileUtils.readFileToByteArray(new File("d:\\workspace\\temp\\keystore")); 
     KeyStore keyStore = KeyStore.getInstance("JKS"); 
     keyStore.load(new ByteArrayInputStream(bytes), "changeit".toCharArray()); 
     KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("X509"); 
     keyManagerFactory.init(keyStore, "changeit".toCharArray()); 

     bytes = FileUtils.readFileToByteArray(new File("d:\\workspace\\temp\\truststore")); 
     KeyStore trustStore = KeyStore.getInstance("JKS"); 
     trustStore.load(new ByteArrayInputStream(bytes), "changeit".toCharArray()); 
     TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("X509"); 
     trustManagerFactory.init(trustStore); 

     SSLContext context = SSLContext.getInstance("TLS"); 
     context.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null); 
     SSLSocketFactory socketFactory = context.getSocketFactory(); 

     connection.setSSLSocketFactory(socketFactory); 
    } 

} 

UPDATE

Ho testato il servizio con .net cliente WCF ed è stato in grado di invoca il serv ghiaccio con successo, quindi mi chiedo quale potrebbe essere il problema? Perché il client WCF è in grado di richiamare il servizio e il client Java, anche se l'ordinaria richiesta HTTP POST HTTP con UrlConnection non è?


UPDATE

Qui è campione di messaggio SOAP

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> 
    <soap:Body> 
     <DoSomethingUseful xmlns="http://namespace/2012/01/service"> 
     ... 
     </DoSomethingUseful> 
    </soap:Body> 
</soap:Envelope> 

UPDATE

mi è stato detto che sul lato servizio .NET ci sono "Client certificate is required. No certificate was found in the request" messaggi che sembrano verificarsi sulla ripresa della sessione ssl. Succede solo quando Content-Length è maggiore di 48680 byte. Anche il servizio WCF è configurato con basicHttpBinding per utilizzare la sicurezza del livello di trasporto.

+0

Potrebbe fornire la configurazione del servizio WCF? –

+0

Sfortunatamente questo è il servizio esterno utilizzato dall'organizzazione per cui lavoro. Probabilmente otterrò la configurazione entro lunedì. Il problema si verifica solo quando sto cercando di inviare la richiesta che è abbastanza grande. Quando si riceve una risposta importante non ci sono problemi. Lo sviluppatore del servizio WCF afferma che non ci sono problemi con la chiamata di questo servizio utilizzando il client .net dalla loro rete interna. – szhem

+0

Stanno usando lo stesso endpoint dalla propria rete interna? –

risposta

1

Hai provato a guardare i pacchetti effettivamente inviati, ad es. con tcpdump/Wireshark (http://www.wireshark.org/)?

Una volta ho avuto problemi solo su alcune piattaforme che raggiungevano un servizio che era dietro un motore offload SSL molto schizzinoso.

+0

Ho. Sfortunatamente dal lato java non c'è nulla di speciale. Ecco come appare l'interazione: 1. un _ack push_ dal client java al servizio .net; 2. leggere time out; 3. _ack fin_ pacchetto dal client java al servizio .net; 4. Il servizio di rete risponde con _ack_ – szhem

+0

. Il client net è fornito dagli sviluppatori del servizio, quindi devo chiedere loro di modificarlo un po '. Ti farò sapere presto i risultati. – szhem

+0

Ciao, @anders. Ho pubblicato la risposta a questa domanda. Il problema era nella rinegoziazione di tls. – szhem

0

hai chiesto, che cosa potrebbe essere il problema, qui qualche suggerimento:

  • la dimensione della vostra richiesta. Questo è fondamentalmente la tua assunzione, se capisco bene.
  • la struttura della richiesta.
  • un criterio lato server, come la richiesta deve essere inferiore a 48681 byte. In un commento ci dici che stai utilizzando un server esterno, non sotto il tuo controllo
  • un bug lato server. Ricorda il non sotto la tua parte di controllo e leggi come buggy.
  • una condizione di gara.

Vorrei suggerire di provare una gamma più ampia di richiesta. Non solo variare le dimensioni.

+0

- Il problema non è sicuramente nella quota, poiché .net client è in grado di inviare richieste più grandi - Non penso che la struttura della richiesta sia un problema, in quanto è stata presa dalla traccia di .net client - I criteri del lato server, come accennato in precedenza nell'argomento, consentono richieste molto più grandi – szhem

0

Avete provato a inviare richiesta dallo strumento SOAPUI e controllare se si comporta allo stesso modo. Vale anche la pena guardare il link sottostante che tratta qualcosa sui servizi WCF e sul client Java.

Java Client and WCF Service

0

Questa potrebbe essere una mancata corrispondenza versione SOAP. La versione predefinita per basichttpbinding è SOAP 1.1. Se il client java sta utilizzando SOAP 1.2, si verificherà un errore.

Abbiamo spesso visto che l'errore si verifica quando la versione SOAP non corrisponde, non ha nulla a che fare con gli errori reali.

+0

Java utilizza soap 1.1. Spiacente che questo non sia chiaramente visibile, ma lo spazio dei nomi di soap negli esempi è * http: //schemas.xmlsoap.org/soap/envelope/*, content-type è * text/xml *. – szhem

0

Infine, ho risolto il problema. Il problema era il seguente:

  1. crittografica fornitore di servizi di un determinato cliente .NET supporta TLS rinegoziazione
  2. provider di crittografia del java-client non supporta TLS rinegoziazione
  3. sul lato del servizio c'era no set di opzioni ClientCertNegotiation, quindi java client non è stato in grado di rinegoziare.
  4. . Il servizio net non rispondeva al java-client che stava aspettando i dati, perché questo servizio prevedeva un certificato client, ma il client non era in grado di fornirlo, poiché la rinegoziazione non è supportata.
+0

Buono a sentirti risolto. –

Problemi correlati