我真的不知道如何解决这个问题,这个项目它是一个Android和iOs应用程序与Docker容器服务器上的RoR后端API ...Android Retrofit和OkHttpClient错误在后端SSL握手让我们加密认证
在Android应用程序中,我使用了Retrofit Library来实现api客户端实现,并且一切工作都很完美......直到SSL证书在服务器上实现为止。我的合作伙伴使用Let’s Encrypt对于这一点,我可以要求成功地与卷曲的API,邮递员......但我的Android应用总说:
D/Error: SSL handshake aborted: ssl=0xXXXXXXXX: I/O error during system call, Connection reset by peer
或有时:
D/Error: SSL handshake timeout
的ApiClient来源:
public class ApiClient {
public static final String DOMAIN = "qwerty.xyz"; //not the real url obviously
public static final String BASE_URL = "https://api." + DOMAIN;
private static Retrofit retrofit = null;
private static OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
private static Gson gson = new GsonBuilder()
.create();
private static Retrofit.Builder builder =
new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create(gson));
public static S createService(Class serviceClass) {
return createService(serviceClass, null, null);
}
public static S createService(Class serviceClass, String username, String password) {
Retrofit retrofit = builder.client(getUnsafeOkHttpClient())
.build();
return retrofit.create(serviceClass);
}
public static OkHttpClient getUnsafeOkHttpClient() {
try {
// Create a trust manager that does not validate certificate chains
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[0];
}
} };
// Install the all-trusting trust manager
final SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
// Create an ssl socket factory with our all-trusting manager
final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
OkHttpClient okHttpClient = httpClient.sslSocketFactory(sslSocketFactory).hostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
})
.build();
return okHttpClient;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
的观察,SSLSocketFactory的方法已不...但我不知道怎么是新的方式来做到这一点...
我使用'com.squareup.retrofit2:翻新:2.2.0'...
我真的很感激任何帮助找到解决方案。
UPDATE & SOLUTION
让我们使用加密协议TLSv1.2工作,而不是自签名的,我们需要排除年长的版本TSL的。
我创建一个自定义的SSLSocketFactory做到这一点:
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() throws IOException {
return enableTLSOnSocket(internalSSLSocketFactory.createSocket());
}
@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.2"});
}
return socket;
}
}
,然后我们和这与信任管理器HttpClient的:
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[0];
}
} };
client = httpClient.sslSocketFactory(new TLSSocketFactory(), (X509TrustManager)trustAllCerts[0])
.build();
Retrofit retrofit = builder.client(client)
.build();
,瞧!
2017-05-13
lromano
+0
您是否拥有SSL的.crt文件?您也可以在本地包含.crt文件并将其添加到您的OkHttp客户端中。 –
+0
它不是静态的,它总是更新的证书 –
+0
您应该检查服务器上启用的密码。另外,是否有任何理由试图绕过证书验证? –