javax.net.ssl.SSLHandshakeException:当禁用SSLv2和SSlv3(仅限TLS)(及更高版本)时,Android 5.0.0上的握手失败
这是我的第一篇文章,我将尽我最大的努力让自己尽可能清楚(对不起我的英语) 这是我的问题,我正在使用改进:1.9.0和okhttp:2.7.5来执行API调用。一切都很好,直到我的服务器提供商禁用SLLv2和SSLv3导致安全问题(3月1日发现溺水故障) 现在,我检查了有关我的提供商的信息,他只允许使用密码TLSv1(TLS 1.0 TLS_RSA_with_3DES_EDE_CBC_SHA No FS) 这是我做的所有测试和结果: [更新问题已解决] 在我的第二个答案中找到解决这个问题的方法 更新 问题似乎来自于GoogleAPI版本。当我在API 18上测试时,一切都正常。当它在Android greather或等于5.0.0时失败 第一次测试 配置重述:javax.net.ssl.SSLHandshakeException:当禁用SSLv2和SSlv3(仅限TLS)(及更高版本)时,Android 5.0.0上的握手失败,java,android,ssl,https,retrofit,Java,Android,Ssl,Https,Retrofit,这是我的第一篇文章,我将尽我最大的努力让自己尽可能清楚(对不起我的英语) 这是我的问题,我正在使用改进:1.9.0和okhttp:2.7.5来执行API调用。一切都很好,直到我的服务器提供商禁用SLLv2和SSLv3导致安全问题(3月1日发现溺水故障) 现在,我检查了有关我的提供商的信息,他只允许使用密码TLSv1(TLS 1.0 TLS_RSA_with_3DES_EDE_CBC_SHA No FS) 这是我做的所有测试和结果: [更新问题已解决] 在我的第二个答案中找到解决这个问题的方法 更
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;
}
}
- 编译DK23版
- buildToolsVersion'23.0.2'
- 明斯克版本18
- targetSdkVersion 21
- 改装:1.9.0
- okhttp:2.7.5
- Android版本>5.0.0(但在每台设备上都是一样的…)
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()
导致自定义回调的公共无效失败(错误)
java.net.UnknownServiceException:找不到可接受的协议。isFallback=false,modes=[ConnectionSpec(密码套件=[TLS_RSA_WITH_3DES_EDE_CBC_SHA],TLS版本=[TLS_1_0],supportsTlsExtensions=true)],支持的协议=[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\u GET\u SERVER\u HELLO:sslv3警报握手失败(外部/openssl/SSL/s23\u clnt.c:770 0x7f87c2fdf0:0x00000000)
如果有人能帮我,那就太酷了。我的所有应用程序都已关闭,从昨天早上开始,我一直在努力解决这个问题,以恢复我的服务。我正在一个接一个地脱发
提前感谢。问题已解决:
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;
}
}
大家好,经过3天3夜的战斗,这里是最终的解决方案。
因此,感谢这里的解决方案:
这个图书馆:
它允许Android在SSLv2和SSlv3被禁用的情况下提供更好的方式来使用cypher和TLS
首先创建此类NoSSLv3SocketFactory.java,并通过创建如下构造函数将其与CypherUrl连接耦合
public NoSSLv3SocketFactory(URL sourceUrl) throws IOException {
this.delegate = NetCipher.getHttpsURLConnection(sourceUrl).getDefaultSSLSocketFactory();
}
NoSSLv3SocketFactory.java(完整代码)
然后,在我的例子中,当您创建RestAdapter时,只需这样做,不要忘记设置您的客户端
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(ApiIntentService.createClient(60, TimeUnit.SECONDS, 20, TimeUnit.SECONDS))
.build();
apiService = restAdapter.create(LoginApiService.class);
}
public LoginApiService getApiService() {
return apiService;
}
}
有了这个,它应该可以工作了。
我希望它对其他人有用。我在这里找到了解决方案 您只需在Android应用程序类中放置以下代码。这就足够了。无需对改装设置进行任何更改。它救了我一天
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
try {
// Google Play will install latest OpenSSL
ProviderInstaller.installIfNeeded(getApplicationContext());
SSLContext sslContext;
sslContext = SSLContext.getInstance("TLSv1.2");
sslContext.init(null, null, null);
sslContext.createSSLEngine();
} catch (GooglePlayServicesRepairableException | GooglePlayServicesNotAvailableException
| NoSuchAlgorithmException | KeyManagementException e) {
e.printStackTrace();
}
}
}
希望这会有所帮助。谢谢。如果您使用的是OkHttpClient use,请检查是否包含了https://而不是将http://发送到您的服务器
OkHttpClient.Builder client = new OkHttpClient.Builder();
client.connectionSpecs(Arrays.asList(ConnectionSpec.COMPATIBLE_TLS));
设置客户端时使用do client.build()。这对我有效:此解决方案解决了我的问题:我找到了解决方案并回答了。嗨,kevzzz,你能帮我解决我的问题吗?一个非常类似的解决方案以前对我有效。我从这里取了下来:不知什么原因,它似乎不再起作用了。然而,Taz的解决方案似乎正在发挥作用。太好了,它帮助了我!你知道kevzzz的解决方案有什么不同吗?几个月前它对我有效,但现在不再有效了。Android框架有什么变化吗?无论如何,我很高兴找到了你的解决方案!这救了我,因为我已经找了好几天了,为什么有些手机无法连接,而我却无法使用
OkHttpClient.Builder client = new OkHttpClient.Builder();
client.connectionSpecs(Arrays.asList(ConnectionSpec.COMPATIBLE_TLS));