我真的不知道如何解决这个问题,这个项目是一个Android和iOs应用程序,在Docker容器服务器上有一个RoR后端API ......
在Android应用程序中,我使用Retrofit Library进行api客户端实现,一切都运行良好......直到在服务器上实现SSL证书。我的合作伙伴使用了Let’s Encrypt,我可以使用curl,postman成功地在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方法已弃用......但我不知道新方法是怎么做的......
我正在使用&#39; com.squareup.retrofit2:改装:2.2.0&#39; ...
我非常感谢您寻求解决方案的任何帮助。
更新&amp;解
让加密使用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();
瞧!!