java certificate - Caricamento di un file su SSL con Certificato lato client e HttpsURLConnection di Android




self use (3)

Sto cercando di caricare un file su un servizio Web protetto con SSL e richiede un certificato sul lato client (firmato da una CA interna). La comunicazione con il servizio web funziona bene (scaricare file, interrogare, eseguire comandi ed eseguire tutti i tipi di POST funziona come previsto), eccetto per il caricamento di file .

Durante il caricamento dei file ricevo una SSLException (javax.net.ssl.SSLException) che dice "Errore di scrittura: ssl = 0x5fe209c0: errore I / O durante la chiamata di sistema, Connessione ripristinata dal peer".

Ho creato un server duplicato e rimosso i requisiti SSL e Client-Certificate, e ho provato a caricare su HTTP "vanilla", e funziona perfettamente.

Ho provato a utilizzare setFixedLengthStreamingMode(int) e setChunkedStreamingMode(int) senza successo. Quando li si utilizza, l'eccezione viene generata dal metodo write e, quando non si utilizza nessuno di essi, viene generata la stessa eccezione dalla chiamata a getResponseCode() .

Non sono riuscito a trovare nulla sull'errore in EventVwr del server.

Il nostro altro client (client iOS) è in grado di caricare file lì, quindi deve essere qualcosa che faccio - ma non riesco a capire cosa.

Non sono sicuro di come eseguire il debug di questo problema ulteriormente.

Per favore aiuto.

Modifica 1

Abbiamo fatto molti sforzi di debug e abbiamo scoperto che:

  • I file di piccole dimensioni vengono caricati come previsto (44kb è la dimensione del file più grande che è stato caricato con successo e caricato in ~ 1200ms).
  • Impossibile caricare un file da 46 kb. L'errore è durato circa 2 minuti (134120 ms).

Modifica 2

Dopo quello che leggerete nei commenti, ora ho fatto giocare a Fiddler (grazie a questa domanda ). Fiddler ha ottenuto il file, ma non è riuscito a inviarlo. Le richieste (raw) assomigliano a:

POST https://192.168.2.2/rest/transfer/strong/Upload/Full?Path=%5C20140807_113255_20.jpg&Root=2 HTTP/1.1
SessionToken: 1234 // We use this for session management
FileMetadata: {"FileSize":"1315496","FileName":"GrumpyCat.jpg"}
Connection: Keep-Alive
User-Agent: Dalvik/1.6.0 (Linux; U; Android 4.1.1; GT-N7100 Build/JRO03C)
Host: 192.168.2.2
Accept-Encoding: gzip
Content-Type: application/x-www-form-urlencoded
Content-Length: 1315496

;odiao;awriorijgoeijoeirj;oedfrvgerg... // The image

La risposta di Fiddler (anche RAW) era:

HTTP/1.1 504 Fiddler - Send Failure
Date: Wed, 20 Aug 2014 17:40:29 GMT
Content-Type: text/html; charset=UTF-8
Connection: close
Timestamp: 20:40:29.420

[Fiddler] ResendRequest() failed: Unable to write data to the transport connection: An existing connection was forcibly closed by the remote host. < An existing connection was forcibly closed by the remote host                                                                                                                                                                                                                                                                                                              

Inoltre, abbiamo aggiunto "MessageLogging" di WCF e "Tracing" dettagliato. MessageLogging non mostra alcun suggerimento del messaggio (probabilmente lasciato cadere prima di trasformarsi in un messaggio), ma la traccia ha mostrato questo:

Ora, prima di dire "ahhh, questo è un problema del server", tieni presente che i file da 44kb riescono a caricare e la nostra app per iOS è anche in grado di caricare i file con successo.

Questo è lo stack di chiamate dall'eccezione che il client ottiene:

E/RestClientUploader(3196): javax.net.ssl.SSLException: Write error: ssl=0x5d94b8b0: I/O error during system call, Connection reset by peer
E/RestClientUploader(3196):     at org.apache.harmony.xnet.provider.jsse.NativeCrypto.SSL_write(Native Method)
E/RestClientUploader(3196):     at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl$SSLOutputStream.write(OpenSSLSocketImpl.java:693)
E/RestClientUploader(3196):     at java.io.ByteArrayOutputStream.writeTo(ByteArrayOutputStream.java:231)
E/RestClientUploader(3196):     at libcore.net.http.ChunkedOutputStream.writeBufferedChunkToSocket(ChunkedOutputStream.java:129)
E/RestClientUploader(3196):     at libcore.net.http.ChunkedOutputStream.write(ChunkedOutputStream.java:77)
E/RestClientUploader(3196):     at java.io.DataOutputStream.write(DataOutputStream.java:98)
E/RestClientUploader(3196):     at com.varonis.datanywhere.communication.RestClientUploader.uploadFileToServer(RestClientUploader.java:151)
E/RestClientUploader(3196):     at com.varonis.datanywhere.communication.RestClientUploader.uploadFullFile(RestClientUploader.java:67)
E/RestClientUploader(3196):     at com.varonis.datanywhere.communication.services.FileUploadService.doUpload(FileUploadService.java:128)
E/RestClientUploader(3196):     at com.varonis.datanywhere.communication.services.FileUploadService.onHandleIntent(FileUploadService.java:98)
E/RestClientUploader(3196):     at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:65)
E/RestClientUploader(3196):     at android.os.Handler.dispatchMessage(Handler.java:99)
E/RestClientUploader(3196):     at android.os.Looper.loop(Looper.java:137)
E/RestClientUploader(3196):     at android.os.HandlerThread.run(HandlerThread.java:60)

Answers

Non una risposta, più un lavoro in giro - per il vostro riferimento.

Dopo aver criticato la questione e aver fatto molte ricerche, ci siamo arresi. Abbiamo aperto questo problema con Google e implementato il seguente lavoro:

Per caricare un file, l'app ottiene un token di caricamento tramite un endpoint che richiede il certificato client e successivamente utilizza questo token per caricarlo su un endpoint che non richiede il certificato client (ma comunque su SSL (Https) ).

Sì, si tratta di una piccola violazione della sicurezza, ma dovevamo farlo. L'abbiamo protetto il più possibile ...

Prometto di aggiornarmi quando il ticket di Google verrà aggiornato (e, si spera, risolto).

HTH!



Ci sono molti modi per rappresentare i grandi numeri interi. Le stringhe di personaggi sono semplici e chiunque abbia mai fatto una lunga divisione con carta e penna può scrivere le routine aritmetiche.





java android ssl https ssl-certificate