改造 2.2.0 Android API 24 javax.net.ssl.SSLHandshakeException:握手失败
Posted
技术标签:
【中文标题】改造 2.2.0 Android API 24 javax.net.ssl.SSLHandshakeException:握手失败【英文标题】:Retrofit 2.2.0 Android API 24 javax.net.ssl.SSLHandshakeException: Handshake failed 【发布时间】:2017-08-16 09:20:19 【问题描述】:我正在使用 Retrofit 2.2.0 将图像上传到服务器(使用 Java)。使用 android 设备(三星 Galaxy S6)API 24(内部版本:NRD90M.G920FXXU5EQAC)时,当我尝试发布请求时,此请求失败并出现此错误
javax.net.ssl.SSLHandshakeException: Handshake failed
ps:我尝试将 Retrofit 2.1.0 降级,它运行良好。
【问题讨论】:
用http而不是https试试你的url。 【参考方案1】:我的解决方案是添加更多 OkHttpClient 可接受的密码。自 API 21 起,某些 TLS 证书已被 Android 弃用。这可能会有所帮助:
ConnectionSpec spec = new
ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
.tlsVersions(TlsVersion.TLS_1_2)
.cipherSuites(
CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256)
.build();
OkHttpClient client = new OkHttpClient.Builder()
.connectionSpecs(Collections.singletonList(spec))
.build();
欲了解更多信息,请访问:https://github.com/square/okhttp/wiki/HTTPS
【讨论】:
【参考方案2】:我在 2.2.0 中使用过
创建不验证证书链的信任管理器
final TrustManager[] trustAllCerts = new TrustManager[]
new X509TrustManager()
@Override
public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException
@Override
public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException
@Override
public java.security.cert.X509Certificate[] getAcceptedIssuers()
return new java.security.cert.X509Certificate[];
;
// Install the all-trusting trust manager
HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient.Builder client = new OkHttpClient.Builder();
client.interceptors().add(httpLoggingInterceptor);
client.readTimeout(180, TimeUnit.SECONDS);
client.connectTimeout(180, TimeUnit.SECONDS);
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null, null);
SSLContext sslContext = SSLContext.getInstance("TLS");
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keyStore);
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keyStore, "keystore_pass".toCharArray());
sslContext.init(null, trustAllCerts, new SecureRandom());
client.sslSocketFactory(sslContext.getSocketFactory())
.hostnameVerifier(new HostnameVerifier()
@Override
public boolean verify(String hostname, SSLSession session)
return true;
);
Gson gson = new GsonBuilder().setLenient().create();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(Common.BASE_URL)
.addConverterFactory(GsonConverterFactory.create(gson))
.client(client.build())
.build();
serviceApi = retrofit.create(Api.class);
谢谢,希望对您有所帮助。 有时 ssl 版本 1.2 或更低版本也未安装在服务器端。
【讨论】:
为我工作,但是,我有后续问题。此修复是否意味着您可能会因为接受发送给客户端的任何证书而受到攻击? 这里的keystore_pass是什么? 对我不起作用,而且接受所有内容会使应用易受攻击。以上是关于改造 2.2.0 Android API 24 javax.net.ssl.SSLHandshakeException:握手失败的主要内容,如果未能解决你的问题,请参考以下文章
如何在正文中传递api参数而不是@Query标签android kotlin改造
如何从包含android中API响应的缓存中获取改造缓存数据