Подтвердить что ты не робот

Загрузка файла через SSL с помощью клиентского сертификата и Android HttpsURLConnection

Я пытаюсь загрузить файл в веб-службу, защищенную SSL, и требует сертификат на стороне клиента (подписанный внутренним ЦС). Связь с веб-службой работает хорошо (загрузка файлов, запрос, запуск команд и выполнение всех видов POST файлов хорошо работают, как ожидалось), , за исключением загрузки файлов.

При загрузке файлов я получаю SSLException (javax.net.ssl.SSLException), в котором говорится: "Ошибка записи: ssl = 0x5fe209c0: ошибка ввода-вывода во время системного вызова, подключение reset по peer".

Я создал дублирующий сервер и удалил требования SSL и Client-Certificate и попытался загрузить через 'vanilla' HTTP, и он отлично работает.

Я пробовал использовать setFixedLengthStreamingMode(int) и setChunkedStreamingMode(int) без успеха. При их использовании исключение выбрано из метода write, и, когда оно не используется ни одним из них, одно и то же исключение вызывается из вызова getResponseCode().

Я ничего не мог найти об ошибке на сервере EventVwr.

Наш другой клиент (клиент iOS) может загружать файлы там, поэтому это должно быть то, что я делаю, но я не могу понять, что.

Я не уверен, как отладить эту проблему дальше.

Пожалуйста, помогите.

Изменить 1

Мы много сделали для отладки и обнаружили, что:

  • Маленькие файлы загружаются как ожидалось (44kb - это размер самого большого файла, который был загружен успешно, и он загружен в ~ 1200 мс).
  • Не удалось загрузить файл размером 46kb. Ошибка составила ~ 2 минуты (134120 мс).

Изменить 2

После того, что вы прочтете в комментариях, теперь я получил Fiddler, чтобы играть хорошо (спасибо этот вопрос). Fiddler получил файл, но не смог его отправить. Запросы (raw) выглядят следующим образом:

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

Ответ на Fiddler (также RAW) был:

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                                                                                                                                                                                                                                                                                                              

Кроме того, мы добавили "MessageLogging" WCF и подробный "Трассировка". MessageLogging не показывает никакого намека на сообщение (вероятно, он упал до того, как превратиться в сообщение), но трассировка показала это: The WCF Trace as seen from the SvcTraceViewer

Теперь, прежде чем вы скажете "ahhh, это проблема с сервером", имейте в виду, что 44kb файлы успешно загружаются, и наше приложение iOS также может успешно загружать файлы.

Это стек вызовов из исключения, которое получает клиент:

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)
4b9b3361

Ответ 1

Не ответ, скорее обходной путь, для вашей справки.

После того, как мы решили эту проблему и провели много исследований, мы сдались. Мы открыли эту проблему в Google и реализовали следующую работу:

Чтобы загрузить файл, приложение сначала получает токен загрузки через конечную точку, для которой требуется сертификат клиента, а затем использует этот токен для загрузки в конечную точку, которая не требует сертификата клиента (но все еще по протоколу SSL (Https).).

Да, это незначительное нарушение безопасности, но мы должны были это сделать. Мы защищали это столько, сколько могли.

Я обещаю обновить, когда билет Google будет обновлен (и, надеюсь, решен).

Ответ 2

Немного поздно (поскольку вы уже реализовали обходной путь), но это должно решить проблему: fooobar.com/info/219435/...

Мы столкнулись с одной и той же проблемой, поскольку настройка сертификата сертификата клиента на включена, кажется, единственная вещь, которую помогает шляпа. Посмотрите здесь, как изменить флаг при привязке сертификата:

http://help.sap.com/saphelp_smp305svr/helpdata/en/6f/f0a9b6e1c743d48d1e57235d297c1c/content.htm