Uploading a file over SSL with Client Side Certificate and Android#39;s HttpsURLConnection(使用客户端证书和 Android 的 HttpsURLConnection 通过 SSL 上传文件)
问题描述
我正在尝试将文件上传到受 SSL 保护并需要客户端证书(由内部 CA 签名)的 Web 服务.与 Web 服务的通信运行良好(下载文件、查询、运行命令和执行各种 POST 工作正常),上传文件除外.
上传文件时,我收到一个 SSLException (javax.net.ssl.SSLException),上面写着写入错误:ssl=0x5fe209c0:系统调用期间的 I/O 错误,对等方重置连接".
我创建了一个重复的服务器并删除了 SSL 和客户端证书要求,并尝试通过vanilla"HTTP 上传,它运行良好.
我尝试过使用 ,并实施了以下解决方法:
为了上传文件,应用程序首先通过需要客户端证书的端点获取 上传令牌,然后使用此令牌上传到不需要客户端证书的端点客户端证书(但仍通过 SSL (Https)).
是的,这是轻微的安全漏洞,但我们必须这样做.我们已尽我们所能保护它.
我保证会在 Google 的票证更新(并希望得到解决)时进行更新.
I'm trying to upload a file to a web-service that is protected with SSL and requires a client-side certificate (signed by an in-house CA). The communication to the web-service works well (Downloading files, Querying, running commands and performing all sorts of POSTs works well as expected), except for uploading files.
When uploading files I get an SSLException (javax.net.ssl.SSLException) that says "Write error: ssl=0x5fe209c0: I/O error during system call, Connection reset by peer".
I have created a duplicate server and removed the SSL and Client-Certificate requirements, and tried to upload over 'vanilla' HTTP, and it works perfectly.
I've tried using setFixedLengthStreamingMode(int) and setChunkedStreamingMode(int) without success. When using them, the exception is thrown from the write
method, and when not using any of them, the same exception is thrown from the call to getResponseCode()
.
I couldn't find anything about the error in the server's EventVwr
.
Our other client (iOS client) is able to upload files there, so it must be something that I do - but I can't figure out what.
I'm not sure how to debug this issue further.
Please help.
Edit 1
We've done a lot of debugging efforts, and found that:
- Small files are uploaded as expected (44kb is the size of the largest file that was uploaded successfully, and it uploaded in ~1200ms).
- An 46kb file failed to upload. The failure took ~2 minutes (134120ms).
Edit 2
After what you'll read in the remarks, now I got Fiddler to play nice (Thanks to this question). Fiddler got the file, but did not succeed in sending it. The requests (raw) looks like:
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's response (also RAW) was:
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
Also, We've added WCF's 'MessageLogging' and verbose 'Tracing'. MessageLogging don't show any hint of the message (probably dropped before turning into a message), but the trace showed this:
Now, before you say "ahhh, this is a server problem", keep in mind that 44kb files succeed in uploading, and our iOS app also is able to upload files successfully.
This is the call stack from the exception that the client gets:
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)
Not an answer, more a work-around, for your reference.
After bashing our heads around this issue, and doing a lot of research, we gave up. We've opened this issue with Google, and implemented the following work around:
In order to upload a file, the app first gets an Upload Token via an endpoint that requires the client-certificate, and afterwards uses this token to upload to an endpoint that doesn't require the client certificate (but still over SSL (Https)).
Yes, it's a minor breach of security, but we had to do it. We've protected it as much as we could.
I promise to update when the Google's ticket will be updated (and hopefully resolved).
这篇关于使用客户端证书和 Android 的 HttpsURLConnection 通过 SSL 上传文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:使用客户端证书和 Android 的 HttpsURLConnection 通过 SSL 上传文件
基础教程推荐
- Java 中保存最后 N 个元素的大小受限队列 2022-01-01
- Spring Boot Freemarker从2.2.0升级失败 2022-01-01
- 如何对 HashSet 进行排序? 2022-01-01
- 如何在不安装整个 WTP 包的情况下将 Tomcat 8 添加到 Eclipse Kepler 2022-01-01
- 如何使用 Stream 在集合中拆分奇数和偶数以及两者的总和 2022-01-01
- 如何使用 Eclipse 检查调试符号状态? 2022-01-01
- 首次使用 Hadoop,MapReduce Job 不运行 Reduce Phase 2022-01-01
- 在螺旋中写一个字符串 2022-01-01
- 如何强制对超级方法进行多态调用? 2022-01-01
- 由于对所需库 rt.jar 的限制,对类的访问限制? 2022-01-01