Amazon S3 上传文件 SSL23_GET_SERVER_HELLO握手错误
题外话:今天偶尔来逛逛,发现我真是懒到家了。居然有半年前的留言我都没有来看过,真对不起留言的同学,希望他的问题已经解决了。
这两三天一直被亚马逊S3上传文件的问题困扰着,直到昨天晚上终于搞定了,工作群里一片欢腾,从客户端到服务器数位工程师卡在这个问题上抓耳挠腮了好几天,终于解决了,这就是所谓“光明总出现在最黑暗的时刻”吧,嘿嘿,非常开心,程序员真是容易满足啊。
途中搜索了很多互联上的方案,最终在stackoverflow的一个帖子里找到有价值的参考。而我们国内的站点上关于这方面的信息非常少,所以我来写这个随笔,希望为大家增加一点参考吧。
------------------------------------------------------------正式开始的分割线----------------------------------------------------------------------------
一开始我们的代码是这样,上传一个测试的mp4,我们的需求是文件size不超过10M:
File file = new File(Environment.getExternalStorageDirectory().getPath() + "/0.mp4"); if(!file.exists())
return;
if(!file.isFile())
return;
try {
URL url = new URL("https://secv.s3.amazonaws.com/familytest10099/DFG092833/2016/01/27/10-38-07/0.mp4?AWSAccessKeyId=AKIAIGMMMZARXIK3ZDBA&Expires=1453948689&Signature=uJvHirNhOlCuB5z20NPkYc73qV8%3D");//从自家server签出的S3 地址
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setRequestMethod("PUT");
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(connection.getOutputStream());
FileInputStream fileInputStream = new FileInputStream(file);// 读取文件的数据。
byte[] bufer = new byte[1024];
int len = 0, i = 0;
while ((len = fileInputStream.read(bufer)) != -1) {
bufferedOutputStream.write(bufer, 0, len);
} bufferedOutputStream.flush();
bufferedOutputStream.close(); fileInputStream.close(); int responseCode = connection.getResponseCode();
Log.d("s3_ssltest","Service returned response code " + responseCode);
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
运行结果抛出异常:
javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x54b61708: Failure in SSL library, usually a protocol error
error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure (external/openssl/ssl/s23_clnt.c:741 0x52732cfc:0x00000000)
at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:448)
at com.android.okhttp.Connection.upgradeToTls(Connection.java:146)
at com.android.okhttp.Connection.connect(Connection.java:107)
at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:294)
at com.android.okhttp.internal.http.HttpEngine.sendSocketRequest(HttpEngine.java:255)
at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:206)
at com.android.okhttp.internal.http.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:345)
at com.android.okhttp.internal.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:296)
at com.android.okhttp.internal.http.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:503)
at com.android.okhttp.internal.http.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:136)
at com.spde.switchbox.manager.secu.SecuThread.a(Unknown Source)
at com.spde.switchbox.manager.secu.SecuThread.run(Unknown Source)
Caused by: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x54b61708: Failure in SSL library, usually a protocol error
error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure (external/openssl/ssl/s23_clnt.c:741 0x52732cfc:0x00000000)
at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method)
at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:405)
... 11 more
出错原因是亚马逊s3 服务器端禁用了SSLv3,解决方法是自己extends一个SSLSocketFactory把SSLv3从默认的protocol中remove掉。重写的SSLSocketFactory见附件NoSSLv3Factory.java。
在创建connection之前先调用:
HttpsURLConnection.setDefaultSSLSocketFactory(new NoSSLv3Factory());
这样修改之后SSL的问题解决了,但又抛出一个异常
javax.net.ssl.SSLException: Write error: ssl=0x5ab6f5f8: I/O error during system call, Connection reset by peer
at org.apache.harmony.xnet.provider.jsse.NativeCrypto.SSL_write(Native Method)
at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl$SSLOutputStream.write(OpenSSLSocketImpl.java:693)
at java.io.ByteArrayOutputStream.writeTo(ByteArrayOutputStream.java:231)
at libcore.net.http.RetryableOutputStream.writeToSocket(RetryableOutputStream.java:70)
at libcore.net.http.HttpEngine.readResponse(HttpEngine.java:806)
at libcore.net.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:274)
at libcore.net.http.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:486)
at libcore.net.http.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:134)
at com.example.test.MainActivity$SSLTestRunnable.run(MainActivity.java:73)
at java.lang.Thread.run(Thread.java:856)
原因是http header中没有指定content-type,传输格式是stream
connection.setRequestProperty("Content-Type", "application/octet-stream");
这个异常也解决了。访问成功,但是返回403 Forbidden,网上搜到很多解释说是客户端的时区或者系统时间不对,因为S3上签出的url是有expire date的。但我们出问题的原因是因为服务器签出这个url的时候没有指定Content-type , 又是Content-type的问题,修改签出地址的代码如下:
public static String createUploadUrl(String bucket, String objKey, Date expire){
String url = s3Client.generatePresignedUrl(new GeneratePresignedUrlRequest(bucket, objKey).
withMethod(HttpMethod.PUT).
withContentType("application/octet-stream").
withExpiration(expire)
).toString();
return url;
}
ok,这次终于收到回复200 ok了,视频也上传成功。
困扰三天的问题就这样解决了。总结一下:一个复杂迷茫各种想不通的问题,最终解决的时候往往修改不了几行代码。
额外的说明:我们出问题的平台android版本是4.4.3,openSSL lib的版本是1.0.1e。网上搜集到的信息,SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure 这种问题通常出现在Android 4.x上。
最后是 NoSSLv3Factory.java 的源码
Amazon S3 上传文件 SSL23_GET_SERVER_HELLO握手错误的更多相关文章
- 解决wordpress上传文件出现http错误问题
解决wordpress上传文件出现http错误问题 问题现象 今天上传约1.4m大小的gif文件到wordpress的媒体库时失败,提示http错误. 原因 由于之前一直上传图片都是可以的,所以推测最 ...
- idea 内置tomcat jersey 跨服务器 上传文件报400错误
报错内容 com.sun.jersey.api.client.UniformInterfaceException: PUT http://.jpg returned a response status ...
- FTP上传文件提示550错误原因分析。
今天测试FTP上传文件功能,同样的代码从自己的Demo移到正式的代码中,不能实现功能,并报 Stream rs = ftp.GetRequestStream()提示远程服务器返回错误: (550) 文 ...
- HipChat上传文件报未知错误解决方案
前言 HipChat是Atlassian公司的一款团队协作即时通讯工具,服务端为Linux(官方给的服务端就是一个虚拟机),在Windows.Linux.Android.IOS.Mac等平台都有客户端 ...
- PHP上传文件详解 错误提示
首先在php.ini里配置上载文件.有以下几个重要的配置单: 选项 默认值 说明 post_max_size 8M 控制以后的POST请求的最大规模.必须大于upload_max_filesize选项 ...
- php上传文件时出现错误:failed to open stream: Permission denied
尝试使用php写了一段小的上传程序,但是在使用的时候,在上传文件时出现这个错误,由于之前在写程序要读文件,曾经出现过这个问题,当时是因为要读的文件的权限不够,于是使用chmod 775 1.txt把文 ...
- 上传文件 nginx 413错误
nginx : 413 Request Entity Too Large 上传文件过程发生413 Request Entity Too Large错误,翻译为请求实体过大,断定为nginx限制了请求体 ...
- SharePoint REST 上传文件请求403错误
最近,需要在SharePoint上传文件到文档库,但是,上传的过程报错了. 错误代码 { "error": { "code": "-213057525 ...
- 最近上传图片上传文件报413错误及仅Https下报413问题,IIS高版本的配置方案及Web.config配置全解
IIS文件上传大小限制30M,C盘中有的IIS_schema.xml文件 C:\Windows\System32\inetsrv\config\schema\ 但是考虑到安全等问题,而且这个文件默认是 ...
随机推荐
- [wikioi]多源最短路
http://wikioi.com/problem/1077/ Floyd算法.精华是三层循环,if (dist(i,k) + dist(k,j) < dist(i,j)) then dist( ...
- SPRING IN ACTION 第4版笔记-第三章ADVANCING WIRING-002-激活PROFILE、设置默认值、@ActiveProfiles
一. Spring honors two separate properties when determining which profiles are active:spring.profiles. ...
- C#功能扩张方式
有时候,为了完成一些window的一些操作,需要引入一些dll进行操作 1) 引入系统api进行操作,形如[DllImport("urlmon.dll", CharSet = C ...
- 一起啃PRML - 1.2 Probability Theory 概率论
一起啃PRML - 1.2 Probability Theory @copyright 转载请注明出处 http://www.cnblogs.com/chxer/ A key concept in t ...
- HDOJ -- 4699
Editor Time Limit: 3000/2000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Total Su ...
- Interleaving String——Leetcode
Given s1, s2, s3, find whether s3 is formed by the interleaving of s1 and s2. For example,Given:s1 = ...
- Ubuntu安装secureCRT
在使用secureCRT前确保主机的ssh服务是启动状态. 一.下载secureCRT包 site: https://www.vandyke.com/download/securecrt/downl ...
- UVA 10652 Board Wrapping(凸包)
题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=32286 [思路] 凸包 根据角度与中心点求出长方形所有点来,然后就 ...
- C语言volatile关键字
volatile提醒编译器它后面所定义的变量随时都有可能改变,因此编译后的程序每次需要存储或读取这个变量的时候,都会直接从变量地址中读取数据.如果没有volatile关键字,则编译器可能优化读取和存储 ...
- WORD文档的长串数字如何粘贴到excel
有问题,才有提高 问题描述: 现 word 文档中有好多长长的数字(如下),我需要将它们弄进 Excel 中 直接[复制],[粘贴],结果显示如下: 然后再设置单元格格式中的数字,无论选哪一个都得不到 ...