使用客户端证书和 Android 的 HttpsURLConnection 通过 SSL 上传文件

2022-09-01 19:34:32

我正在尝试将文件上传到受 SSL 保护且需要客户端证书(由内部 CA 签名)的 Web 服务。与Web服务的通信运行良好(下载文件,查询,运行命令和执行各种POST按预期工作),除了上传文件

上传文件时,我得到一个SSLException(javax.net.ssl.SSLException),上面写着“写入错误:ssl=0x5fe209c0:系统调用期间的I / O错误,对等体重置连接”。

我已经创建了一个重复的服务器,并删除了SSL和客户端证书要求,并尝试通过“vanilla”HTTP上传,并且它工作得很好。

我尝试过使用setFixedLengthStreamingMode(int)setChunkedStreamingMode(int),但没有成功。使用它们时,将从方法引发异常,并且当不使用其中任何一个时,从对 的调用中引发相同的异常。writegetResponseCode()

我在服务器的.EventVwr

我们的另一个客户端(iOS客户端)能够在那里上传文件,所以它一定是我做的事情 - 但我不知道是什么。

我不确定如何进一步调试此问题。

请帮忙。

编辑 1

我们做了很多调试工作,发现:

  • 小文件按预期上传(44kb 是成功上传的最大文件的大小,上传时间约为 1200 毫秒)。
  • 46kb 文件上传失败。失败需要大约 2 分钟 (134120ms)。

编辑 2

在你将在评论中读到的内容之后,现在我让小提琴手玩得很好(感谢这个问题)。Fiddler拿到了文件,但没有成功发送。请求(原始)如下所示:

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

小提琴手的回应(也是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                                                                                                                                                                                                                                                                                                              

此外,我们还添加了 WCF 的“消息日志记录”和详细的“跟踪”。MessageLogging 不显示任何消息提示(可能在转换为消息之前已丢弃),但跟踪显示如下:The WCF Trace as seen from the SvcTraceViewer

现在,在你说“啊,这是一个服务器问题”之前,请记住,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)

答案 1

不是答案,更多的是解决方法,供您参考。

在围绕这个问题捶打我们的头并做了很多研究之后,我们放弃了。我们已向 Google 打开了此问题,并实施了以下解决方法:

为了上传文件,应用首先通过需要客户端证书的终结点获取上传令牌,然后使用此令牌上传到不需要客户端证书(但仍通过 SSL (Https))的终结点。

是的,这是一个轻微的安全漏洞,但我们必须这样做。我们尽可能地保护它。

我承诺在Google的票证更新(并希望得到解决)时进行更新。


答案 2

这有点晚了(因为您已经实施了解决方法),但这应该可以解决问题:https://stackoverflow.com/a/9224892/1619545

我们遇到了同样的问题,将客户端证书协商标志设置为启用似乎是帽子唯一有帮助的事情。请在此处查看有关如何更改证书绑定处的标志的方法:

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