Retrofit2 上带有 HTTPs 的 SSLProtocolException
SSLProtocolException with HTTPs on Retrofit2
我 运行 遇到了 Android 4.4 phones 的问题(特别是 Galaxy S4,尽管我认为这不是 phone 本身的错) .使用 Retrofit2.Http 时,我在通过 HTTPS 连接时收到以下错误:
javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x737510d0: 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 0x727fb7d0:0x00000000)
我发现了一些资源表明这是 Android 4.4(1) 上的错误,但给出的示例始终假定使用了我没有使用的 HttpsUrlConnection class。
我确实在这里找到了一些关于为连接设置特定的 ConnectionSpec 实例的答案,这看起来很有希望,因为它是 Retrofit-specific(2)。不幸的是,这对错误没有影响。我的代码示例(我尝试了 MODERN_TLS 和 COMPATIBLE_TLS):
return new OkHttpClient.Builder()
.addInterceptor(interceptor)
.connectionSpecs(Collections.singletonList(ConnectionSpec.MODERN_TLS))
.build();
切换到 "http" 确实有效,但这不是最终版本的选项。绝对需要安全、加密的连接,因此任何完全禁用 HTTPS 或盲目接受任何证书的解决方案都不太可能被接受。
提前致谢!
(1)
(2)
编辑:
运行 openssl 给出以下内容:
[[my_computer]]$ ./openssl s_client -connect [[server_hidden_by_me]]:443 -tls1
CONNECTED(00000003)
depth=2 /C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Certification Authority
verify error:num=20:unable to get local issuer certificate
verify return:0
---
Certificate chain
0 s:/OU=Domain Control Validated/OU=PositiveSSL/CN=[hidden_by_me]
i:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Domain Validation Secure Server CA
1 s:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Domain 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
---
Server certificate
-----BEGIN CERTIFICATE-----
[snip certificate for brevity]
-----END CERTIFICATE-----
subject=/OU=Domain Control Validated/OU=PositiveSSL/CN=[hidden_by_me]
issuer=/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Domain Validation Secure Server CA
---
No client certificate CA names sent
---
SSL handshake has read 5449 bytes and written 426 bytes
---
New, TLSv1/SSLv3, Cipher is DHE-RSA-SEED-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
Protocol : TLSv1
Cipher : DHE-RSA-SEED-SHA
Session-ID: A4D84E2A0A16DB03082172695141BE1BB562F920ED4E4F6A9139733D9CAB7A54
Session-ID-ctx:
Master-Key: 119C10E5CC34297D1717E4AEAB8BF1CAA8BA012C125B10513FBFE0854B6AB0E9E65536F801990CA3C992FEB69ADBE279
Key-Arg : None
TLS session ticket lifetime hint: 300 (seconds)
TLS session ticket:
0000 - 5c 21 2c ac 68 a9 ef 71-8c 69 2a 86 0c da 6c cd \!,.h..q.i*...l.
[snipped for brevity]
Start Time: 1464109807
Timeout : 7200 (sec)
Verify return code: 0 (ok)
---
Nexus 7 (Android 4.4.4) 也有类似问题。发现它尝试通过 TLSv1 进行连接,而 TLSv1 在我的服务器上默认情况下未启用。通过启用它修复 =)
您可以使用 openssl 测试您的服务器:
openssl s_client -connect google.com:443 -tls1
更新:
此代码在我的设备上强制使用 TLSv1,顺便说一句,它仅支持 SSLv3、TLSv1。使用 okhttp:3.3.0
测试
ConnectionSpec spec = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
.tlsVersions(TlsVersion.TLS_1_0)
.allEnabledCipherSuites()
.build();
OkHttpClient client = new OkHttpClient.Builder()
.connectionSpecs(Collections.singletonList(spec))
.build();
Request request = new Request.Builder()
.url("https://192.168.0.19:44330")
.build();
try {
client.newCall(request).execute();
} catch (IOException e) {
e.printStackTrace();
}
使用过openssl服务器查看它真正使用的协议版本,您将需要证书和密钥文件:
openssl s_server -key key.pem -cert cert.cer -accept 44330 -www -msg
希望对您有所帮助!
我 运行 遇到了 Android 4.4 phones 的问题(特别是 Galaxy S4,尽管我认为这不是 phone 本身的错) .使用 Retrofit2.Http 时,我在通过 HTTPS 连接时收到以下错误:
javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x737510d0: 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 0x727fb7d0:0x00000000)
我发现了一些资源表明这是 Android 4.4(1) 上的错误,但给出的示例始终假定使用了我没有使用的 HttpsUrlConnection class。
我确实在这里找到了一些关于为连接设置特定的 ConnectionSpec 实例的答案,这看起来很有希望,因为它是 Retrofit-specific(2)。不幸的是,这对错误没有影响。我的代码示例(我尝试了 MODERN_TLS 和 COMPATIBLE_TLS):
return new OkHttpClient.Builder()
.addInterceptor(interceptor)
.connectionSpecs(Collections.singletonList(ConnectionSpec.MODERN_TLS))
.build();
切换到 "http" 确实有效,但这不是最终版本的选项。绝对需要安全、加密的连接,因此任何完全禁用 HTTPS 或盲目接受任何证书的解决方案都不太可能被接受。
提前致谢!
(1)
(2)
编辑:
运行 openssl 给出以下内容:
[[my_computer]]$ ./openssl s_client -connect [[server_hidden_by_me]]:443 -tls1
CONNECTED(00000003)
depth=2 /C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Certification Authority
verify error:num=20:unable to get local issuer certificate
verify return:0
---
Certificate chain
0 s:/OU=Domain Control Validated/OU=PositiveSSL/CN=[hidden_by_me]
i:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Domain Validation Secure Server CA
1 s:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Domain 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
---
Server certificate
-----BEGIN CERTIFICATE-----
[snip certificate for brevity]
-----END CERTIFICATE-----
subject=/OU=Domain Control Validated/OU=PositiveSSL/CN=[hidden_by_me]
issuer=/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Domain Validation Secure Server CA
---
No client certificate CA names sent
---
SSL handshake has read 5449 bytes and written 426 bytes
---
New, TLSv1/SSLv3, Cipher is DHE-RSA-SEED-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
Protocol : TLSv1
Cipher : DHE-RSA-SEED-SHA
Session-ID: A4D84E2A0A16DB03082172695141BE1BB562F920ED4E4F6A9139733D9CAB7A54
Session-ID-ctx:
Master-Key: 119C10E5CC34297D1717E4AEAB8BF1CAA8BA012C125B10513FBFE0854B6AB0E9E65536F801990CA3C992FEB69ADBE279
Key-Arg : None
TLS session ticket lifetime hint: 300 (seconds)
TLS session ticket:
0000 - 5c 21 2c ac 68 a9 ef 71-8c 69 2a 86 0c da 6c cd \!,.h..q.i*...l.
[snipped for brevity]
Start Time: 1464109807
Timeout : 7200 (sec)
Verify return code: 0 (ok)
---
Nexus 7 (Android 4.4.4) 也有类似问题。发现它尝试通过 TLSv1 进行连接,而 TLSv1 在我的服务器上默认情况下未启用。通过启用它修复 =)
您可以使用 openssl 测试您的服务器:
openssl s_client -connect google.com:443 -tls1
更新:
此代码在我的设备上强制使用 TLSv1,顺便说一句,它仅支持 SSLv3、TLSv1。使用 okhttp:3.3.0
测试ConnectionSpec spec = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
.tlsVersions(TlsVersion.TLS_1_0)
.allEnabledCipherSuites()
.build();
OkHttpClient client = new OkHttpClient.Builder()
.connectionSpecs(Collections.singletonList(spec))
.build();
Request request = new Request.Builder()
.url("https://192.168.0.19:44330")
.build();
try {
client.newCall(request).execute();
} catch (IOException e) {
e.printStackTrace();
}
使用过openssl服务器查看它真正使用的协议版本,您将需要证书和密钥文件:
openssl s_server -key key.pem -cert cert.cer -accept 44330 -www -msg
希望对您有所帮助!