javax.net.ssl.SSLHandshakeException:当禁用 SSLv2 和 SSlv3 时,Android 5.0.0 上的握手失败(仅限 TLS)(及更高版本)
这是我的第一篇文章,我将尽力做到尽可能清晰(对不起我的英语)。
这是我的麻烦,我正在使用reformition:1.9.0和okhttp:2.7.5来执行API调用。一切都很好,直到我的服务器提供商禁用SLLv2和SSLv3导致的异常问题(3月1日发现溺水失败)。
现在我检查有关我的提供商的信息,他只允许来自 https://www.ssllabs.com/ 的密码(TLS 1.0 TLS_RSA_WITH_3DES_EDE_CBC_SHA No FS)的TLSv1。
好的,这就是我做过的所有测试和结果:
[更新问题已解决]
在我的第二个答案中找到解决这个问题的方法。
更新似乎问题来自谷歌API版本。当我在API 18上测试时,一切正常。当它在Android上或等于5.0.0时,它会失败。
第一次测试
会议回顾:
- 编译SdkVersion 23
- buildToolsVersion '23.0.2'
- minSdkVersion 18
- targetSdkVersion 21
- 改造:1.9.0
- 确定http:2.7.5
- Android版本>5.0.0(但每台设备上都是一样的...)
Rest Client (LoginRestClient):
public class LoginRestClient
{
private static final String BASE_URL = "";
private LoginApiService apiService;
public LoginRestClient()
{
Gson gson = new GsonBuilder()
.setDateFormat("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'SSS'Z'")
.create();
RestAdapter restAdapter = new RestAdapter.Builder()
.setLogLevel(RestAdapter.LogLevel.FULL)
.setEndpoint(ApiIntentService.getHostAddress())
.setConverter(new GsonConverter(gson))
.setClient(new OkClient(ApiIntentService.getConnectionHttpClient()))
.build();
apiService = restAdapter.create(LoginApiService.class);
}
public LoginApiService getApiService() {
return apiService;
}
}
创建客户端的函数 OkHttpClient getConnectionHttpClient()
public static OkHttpClient getConnectionHttpClient()
{
OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.setReadTimeout(60, TimeUnit.SECONDS);
okHttpClient.setConnectTimeout(60, TimeUnit.SECONDS);
ConnectionSpec specs = new ConnectionSpec.Builder(ConnectionSpec.COMPATIBLE_TLS)
.tlsVersions(TlsVersion.TLS_1_0)
.cipherSuites(CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA)
.build();
okHttpClient.setConnectionSpecs(Collections.singletonList(specs));
return okHttpClient;
}
导致自定义回调导致公共无效失败(改造错误)
java.net.UnknownServiceException:无法找到可接受的协议。isFallback=false, modes=[ConnectionSpec(cipherSuites=[TLS_RSA_WITH_3DES_EDE_CBC_SHA], tlsVersions=[TLS_1_0], supportsTlsExtensions=true)], support protocols=[SSLv3, TLSv1, TLSv1.1, TLSv1.2]
第二次测试
我做了一个自定义的SSLSocketFactory来禁用SSLv3并强制TLS:
/**
* @author fkrauthan
*/
public class TLSSocketFactory extends SSLSocketFactory {
private SSLSocketFactory internalSSLSocketFactory;
public TLSSocketFactory() throws KeyManagementException, NoSuchAlgorithmException {
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, null, null);
internalSSLSocketFactory = context.getSocketFactory();
}
@Override
public String[] getDefaultCipherSuites() {
return internalSSLSocketFactory.getDefaultCipherSuites();
}
@Override
public String[] getSupportedCipherSuites() {
return internalSSLSocketFactory.getSupportedCipherSuites();
}
@Override
public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(s, host, port, autoClose));
}
@Override
public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port));
}
@Override
public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException {
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port, localHost, localPort));
}
@Override
public Socket createSocket(InetAddress host, int port) throws IOException {
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port));
}
@Override
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(address, port, localAddress, localPort));
}
private Socket enableTLSOnSocket(Socket socket) {
if(socket != null && (socket instanceof SSLSocket)) {
((SSLSocket)socket).setEnabledProtocols(new String[] {"TLSv1"});
}
return socket;
}
}
我这样使用它:
public static OkHttpClient getConnectionHttpClient()
{
OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.setReadTimeout(60, TimeUnit.SECONDS);
okHttpClient.setConnectTimeout(60, TimeUnit.SECONDS);
try {
TLSSocketFactory tlsSocketFactory = new TLSSocketFactory();
HttpsURLConnection.setDefaultSSLSocketFactory(tlsSocketFactory);
okHttpClient.setSslSocketFactory(tlsSocketFactory);
} catch (KeyManagementException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return okHttpClient;
}
导致自定义回调导致公共无效失败(改造错误)
javax.net.ssl.SSLProtocolException: SSL 握手中止: ssl=0x7f87885280: SSL 库中的故障,通常是协议错误错误:14077410:SSL 例程:SSL23_GET_SERVER_HELLO:sslv3 警报握手失败 (external/openssl/ssl/s23_clnt.c:770 0x7f87c2fdf0:0x00000000)
如果有人能帮助我,那将是非常酷的。我的所有应用程序都已关闭,自昨天早上以来,我正在与此问题作斗争,以恢复我的服务。我正在一个接一个地脱掉我的头发...
提前致谢。