2017-05-13 53 views
0

我真的不知道如何解決這個問題,這個項目它是一個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(); 

,瞧!

+0

您是否擁有SSL的.crt文件?您也可以在本地包含.crt文件並將其添加到您的OkHttp客戶端中。 –

+0

它不是靜態的,它總是更新的證書 – lromano

+0

您應該檢查服務器上啓用的密碼。另外,是否有任何理由試圖繞過證書驗證? –

回答

0
+0

對於Retrofit2也不是一個合適的解決方案,也是一個鏈接的唯一答案! –