com.android.volley.NoConnectionError: javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted:
com.android.volley.NoConnectionError: javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted:
我在我的应用程序中使用 Android 中的 Volley 库,当我尝试向我们的服务器发出 POST 请求时,我收到以下错误:
com.android.volley.NoConnectionError: javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x6821edb0: Failure in SSL library, usually a protocol error
error:1407743E:SSL routines:SSL23_GET_SERVER_HELLO:tlsv1 alert inappropriate fallback (external/openssl/ssl/s23_clnt.c:744 0x5f4c0c46:0x00000000)
我们的服务器使用以下 SSL 证书签名:
i:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Organization Validation Secure Server CA
1 s:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Organization Validation Secure Server CA
i:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Certification Authority
2 s:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Certification Authority
i:/C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root
证书由openssl描述如下:
New, TLSv1/SSLv3, Cipher is DHE-RSA-AES256-SHA
我通过 Android 启用的密码检查了密码,他们说它默认启用。
我已经针对这个问题尝试了以下解决方案,但是 none 解决了这个问题:
- 不工作(也不适合我,因为它不安全)
- 我已经试过了,错误仍然存在
out项目中使用的AndroidApi是Android5.1(API22)。
Volley库版本是1.0.15(也试过最新的1.0.18,问题依旧)
我尝试过的另一个解决方案是使用 okhttp 库,与 Volley 集成,但问题仍然存在。
任何可行的解决方案将不胜感激。
提前致谢!
更新
顺便说一句,我设法从服务器获得支持的密码:
Supported cipher suites (ORDER IS NOT SIGNIFICANT):
SSLv3
RSA_WITH_RC4_128_MD5
RSA_WITH_RC4_128_SHA
RSA_WITH_IDEA_CBC_SHA
RSA_WITH_3DES_EDE_CBC_SHA
DHE_RSA_WITH_3DES_EDE_CBC_SHA
RSA_WITH_AES_128_CBC_SHA
DHE_RSA_WITH_AES_128_CBC_SHA
RSA_WITH_AES_256_CBC_SHA
DHE_RSA_WITH_AES_256_CBC_SHA
RSA_WITH_CAMELLIA_128_CBC_SHA
DHE_RSA_WITH_CAMELLIA_128_CBC_SHA
RSA_WITH_CAMELLIA_256_CBC_SHA
DHE_RSA_WITH_CAMELLIA_256_CBC_SHA
TLS_RSA_WITH_SEED_CBC_SHA
TLS_DHE_RSA_WITH_SEED_CBC_SHA
(TLSv1.0: idem)
(TLSv1.1: idem)
TLSv1.2
RSA_WITH_RC4_128_MD5
RSA_WITH_RC4_128_SHA
RSA_WITH_IDEA_CBC_SHA
RSA_WITH_3DES_EDE_CBC_SHA
DHE_RSA_WITH_3DES_EDE_CBC_SHA
RSA_WITH_AES_128_CBC_SHA
DHE_RSA_WITH_AES_128_CBC_SHA
RSA_WITH_AES_256_CBC_SHA
DHE_RSA_WITH_AES_256_CBC_SHA
RSA_WITH_AES_128_CBC_SHA256
RSA_WITH_AES_256_CBC_SHA256
RSA_WITH_CAMELLIA_128_CBC_SHA
DHE_RSA_WITH_CAMELLIA_128_CBC_SHA
DHE_RSA_WITH_AES_128_CBC_SHA256
DHE_RSA_WITH_AES_256_CBC_SHA256
RSA_WITH_CAMELLIA_256_CBC_SHA
DHE_RSA_WITH_CAMELLIA_256_CBC_SHA
TLS_RSA_WITH_SEED_CBC_SHA
TLS_DHE_RSA_WITH_SEED_CBC_SHA
TLS_RSA_WITH_AES_128_GCM_SHA256
TLS_RSA_WITH_AES_256_GCM_SHA384
TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
根据我的阅读,API LVL 22 上的这些密码应该没有问题。
我在互联网和项目代码中搜索了几个小时后发现了问题:
在项目中,我有一个名为 JsonToPOJORequest<T>
的 class,它扩展了 Volley class JsonRequest<T>
。
这是实际对服务器上的每个方法发出请求的 class。
稍微分析了一下代码,发现构造函数内部有一个方法调用,如下:
setRetryPolicy(new DefaultRetryPolicy(3*DefaultRetryPolicy.DEFAULT_TIMEOUT_MS, 0, 0));
其中 DefaultRetryPolicy.DEFAULT_TIMEOUT_MS
设置为 2500 毫秒。
因为 POST 请求有很多数据,发送请求和接收服务器返回的响应需要更多时间。
似乎 Volley 没有等待足够的时间来响应并抛出 TimeoutError。
所以,请求发出了,在服务器上一切顺利,但是客户端(Android)没有等待服务器并得到一个错误。
解决方案是将超时参数设置得更高或为 0,如下所示:
setRetryPolicy(new DefaultRetryPolicy(5*DefaultRetryPolicy.DEFAULT_TIMEOUT_MS, 0, 0));
setRetryPolicy(new DefaultRetryPolicy(0, 0, 0));
剩下的两个问题是:
1) 为什么提出请求需要这么长时间? -> 3*2500 = 7500ms 是相当多的时间(超过 7 秒)来发出请求。这不是服务器问题,因为在 iOS 上它工作得很好。
2) 为什么 VolleyError 看起来像这样?
com.android.volley.NoConnectionError: javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted:
应该是 TimeoutError 而不是 NoConnectionError。
你可以在这里找到关于这个错误的更多信息,我也推导出了解决方案:
Android Volley double post when have slow request
https://groups.google.com/forum/#!topic/volley-users/8PE9dBbD6iA
解决办法就是通过这行代码增加volley的请求超时时间
request.setRetryPolicy(新的默认重试策略(10 * 1000, 0,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
以上代码是设置请求超时为10秒。
我在我的应用程序中使用 Android 中的 Volley 库,当我尝试向我们的服务器发出 POST 请求时,我收到以下错误:
com.android.volley.NoConnectionError: javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x6821edb0: Failure in SSL library, usually a protocol error
error:1407743E:SSL routines:SSL23_GET_SERVER_HELLO:tlsv1 alert inappropriate fallback (external/openssl/ssl/s23_clnt.c:744 0x5f4c0c46:0x00000000)
我们的服务器使用以下 SSL 证书签名:
i:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Organization Validation Secure Server CA
1 s:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Organization Validation Secure Server CA
i:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Certification Authority
2 s:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Certification Authority
i:/C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root
证书由openssl描述如下:
New, TLSv1/SSLv3, Cipher is DHE-RSA-AES256-SHA
我通过 Android 启用的密码检查了密码,他们说它默认启用。
我已经针对这个问题尝试了以下解决方案,但是 none 解决了这个问题:
- 不工作(也不适合我,因为它不安全)
- 我已经试过了,错误仍然存在
out项目中使用的AndroidApi是Android5.1(API22)。 Volley库版本是1.0.15(也试过最新的1.0.18,问题依旧)
我尝试过的另一个解决方案是使用 okhttp 库,与 Volley 集成,但问题仍然存在。
任何可行的解决方案将不胜感激。
提前致谢!
更新
顺便说一句,我设法从服务器获得支持的密码:
Supported cipher suites (ORDER IS NOT SIGNIFICANT):
SSLv3
RSA_WITH_RC4_128_MD5
RSA_WITH_RC4_128_SHA
RSA_WITH_IDEA_CBC_SHA
RSA_WITH_3DES_EDE_CBC_SHA
DHE_RSA_WITH_3DES_EDE_CBC_SHA
RSA_WITH_AES_128_CBC_SHA
DHE_RSA_WITH_AES_128_CBC_SHA
RSA_WITH_AES_256_CBC_SHA
DHE_RSA_WITH_AES_256_CBC_SHA
RSA_WITH_CAMELLIA_128_CBC_SHA
DHE_RSA_WITH_CAMELLIA_128_CBC_SHA
RSA_WITH_CAMELLIA_256_CBC_SHA
DHE_RSA_WITH_CAMELLIA_256_CBC_SHA
TLS_RSA_WITH_SEED_CBC_SHA
TLS_DHE_RSA_WITH_SEED_CBC_SHA
(TLSv1.0: idem)
(TLSv1.1: idem)
TLSv1.2
RSA_WITH_RC4_128_MD5
RSA_WITH_RC4_128_SHA
RSA_WITH_IDEA_CBC_SHA
RSA_WITH_3DES_EDE_CBC_SHA
DHE_RSA_WITH_3DES_EDE_CBC_SHA
RSA_WITH_AES_128_CBC_SHA
DHE_RSA_WITH_AES_128_CBC_SHA
RSA_WITH_AES_256_CBC_SHA
DHE_RSA_WITH_AES_256_CBC_SHA
RSA_WITH_AES_128_CBC_SHA256
RSA_WITH_AES_256_CBC_SHA256
RSA_WITH_CAMELLIA_128_CBC_SHA
DHE_RSA_WITH_CAMELLIA_128_CBC_SHA
DHE_RSA_WITH_AES_128_CBC_SHA256
DHE_RSA_WITH_AES_256_CBC_SHA256
RSA_WITH_CAMELLIA_256_CBC_SHA
DHE_RSA_WITH_CAMELLIA_256_CBC_SHA
TLS_RSA_WITH_SEED_CBC_SHA
TLS_DHE_RSA_WITH_SEED_CBC_SHA
TLS_RSA_WITH_AES_128_GCM_SHA256
TLS_RSA_WITH_AES_256_GCM_SHA384
TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
根据我的阅读,API LVL 22 上的这些密码应该没有问题。
我在互联网和项目代码中搜索了几个小时后发现了问题:
在项目中,我有一个名为 JsonToPOJORequest<T>
的 class,它扩展了 Volley class JsonRequest<T>
。
这是实际对服务器上的每个方法发出请求的 class。
稍微分析了一下代码,发现构造函数内部有一个方法调用,如下:
setRetryPolicy(new DefaultRetryPolicy(3*DefaultRetryPolicy.DEFAULT_TIMEOUT_MS, 0, 0));
其中 DefaultRetryPolicy.DEFAULT_TIMEOUT_MS
设置为 2500 毫秒。
因为 POST 请求有很多数据,发送请求和接收服务器返回的响应需要更多时间。
似乎 Volley 没有等待足够的时间来响应并抛出 TimeoutError。 所以,请求发出了,在服务器上一切顺利,但是客户端(Android)没有等待服务器并得到一个错误。
解决方案是将超时参数设置得更高或为 0,如下所示:
setRetryPolicy(new DefaultRetryPolicy(5*DefaultRetryPolicy.DEFAULT_TIMEOUT_MS, 0, 0));
setRetryPolicy(new DefaultRetryPolicy(0, 0, 0));
剩下的两个问题是:
1) 为什么提出请求需要这么长时间? -> 3*2500 = 7500ms 是相当多的时间(超过 7 秒)来发出请求。这不是服务器问题,因为在 iOS 上它工作得很好。
2) 为什么 VolleyError 看起来像这样?
com.android.volley.NoConnectionError: javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted:
应该是 TimeoutError 而不是 NoConnectionError。
你可以在这里找到关于这个错误的更多信息,我也推导出了解决方案: Android Volley double post when have slow request
https://groups.google.com/forum/#!topic/volley-users/8PE9dBbD6iA
解决办法就是通过这行代码增加volley的请求超时时间
request.setRetryPolicy(新的默认重试策略(10 * 1000, 0, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
以上代码是设置请求超时为10秒。