我真的不知道如何解決這個問題,這個項目它是一個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> S createService(Class<S> serviceClass) {
return createService(serviceClass, null, null);
}
public static <S> S createService(Class<S> 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();
,瞧!
您是否擁有SSL的.crt文件?您也可以在本地包含.crt文件並將其添加到您的OkHttp客戶端中。 –
它不是靜態的,它總是更新的證書 – lromano
您應該檢查服務器上啓用的密碼。另外,是否有任何理由試圖繞過證書驗證? –