2015-07-19 59 views
1

我是新來的任何網絡相關的編程,所以我知道我在深潛,但我必須讓我的Android HttpsURLConnection的之間的成功SSL握手的問題我本地的XAMPP託管網站,而不僅僅是一個返回Hello World的PHP腳本!讓我先說,我可以從我的電腦(主機),並從我的Android手機瀏覽器( HTTPS)加載這個頁面。在SSL庫的Android未能連接到我的本地XAMPP當託管網站

問題:

當我嘗試應用與我的服務器通過HttpsURLConnection的我碰到下面的錯誤連接:

System.err﹕ javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x5e522ba8: Failure in SSL library, usually a protocol error 
System.err﹕ error:1407743E:SSL routines:SSL23_GET_SERVER_HELLO:tlsv1 alert inappropriate fallback (external/openssl/ssl/s23_clnt.c:744 0x5e5967e8:0x00000000) 
System.err﹕ at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:449) 
System.err﹕ at com.android.okhttp.Connection.upgradeToTls(Connection.java:146) 
System.err﹕ at com.android.okhttp.Connection.connect(Connection.java:107) 
System.err﹕ at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:294) 
System.err﹕ at com.android.okhttp.internal.http.HttpEngine.sendSocketRequest(HttpEngine.java:255) 
System.err﹕ at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:206) 
System.err﹕ at com.android.okhttp.internal.http.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:345) 
System.err﹕ at com.android.okhttp.internal.http.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:89) 
System.err﹕ at com.android.okhttp.internal.http.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:161) 
System.err﹕ at yellowgames.battlenetfriendfinder.ServerConnection$TaskExecuter.doInBackground(ServerConnection.java:118) 
System.err﹕ at yellowgames.battlenetfriendfinder.ServerConnection$TaskExecuter.doInBackground(ServerConnection.java:94) 
System.err﹕ at android.os.AsyncTask$2.call(AsyncTask.java:288) 
System.err﹕ at java.util.concurrent.FutureTask.run(FutureTask.java:237) 
System.err﹕ at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231) 
System.err﹕ at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112) 
System.err﹕ at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587) 
System.err﹕ at java.lang.Thread.run(Thread.java:841) 
System.err﹕ Caused by: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x5e522ba8: Failure in SSL library, usually a protocol error 
System.err﹕ error:1407743E:SSL routines:SSL23_GET_SERVER_HELLO:tlsv1 alert inappropriate fallback (external/openssl/ssl/s23_clnt.c:744 0x5e5967e8:0x00000000) 
System.err﹕ at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method) 
System.err﹕ at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:406) 
System.err﹕ ... 16 more 

我的代碼:

我的代碼在此基礎上:https://developer.android.com/training/articles/security-ssl.html

//Get Cert 
try { 
    InputStream CertInputStream = a_sContext.getResources().openRawResource(R.raw.server); 

    //Read Cert 
    CertificateFactory CertFactory = CertificateFactory.getInstance("X.509"); 
    Certificate Cert = CertFactory.generateCertificate(CertInputStream); 
    String Result = "Ca=" + ((X509Certificate) Cert).getSubjectDN(); 
    Log.d("test", Result); //This Returns correct Cert information 

    //Create a keystore 
    KeyStore MyKeyStore = KeyStore.getInstance(KeyStore.getDefaultType()); 
    MyKeyStore.load(null, null); 
    MyKeyStore.setCertificateEntry("ca", Cert); 

    //Create a TrustManager 
    TrustManagerFactory TMF = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); 
    TMF.init(MyKeyStore); 

    //Create a SSLContext 
    m_pSSLContext = SSLContext.getInstance("TLS"); 
    m_pSSLContext.init(null, TMF.getTrustManagers(), null); 
    HttpsURLConnection.setDefaultSSLSocketFactory(m_pSSLContext.getSocketFactory()); 

    //Try and connect to the website 
    URL MyURL = new URL(m_sSecureHttp + m_sWebsite + m_sTestPath); 
    con = (HttpsURLConnection) MyURL.openConnection(); 
    con.connect(); 
    Result = new String(); 
    BufferedReader reader = new BufferedReader(new InputStreamReader(con.getInputStream()));; 
    while((Line = reader.readLine())!= null) { 
     Result += Line; 
    } 
} 
catch (Exception e) { e.printStackTrace(); } 

服務器端:

我生成以下證書:http://robsnotebook.com/xampp-ssl-encrypt-passwords

這似乎是因爲我的本地計算機上工作過和Android瀏覽器可以訪問它。另外,在XAMPP的ssl_request.log中,我可以看到我的本地計算機或我的android瀏覽器的所有連接嘗試,但它甚至沒有提到我的應用程序的請求。這對access.log是一樣的。

我上的是Android 4.4.2

我的實際問題測試Android應用程序

有誰知道我怎麼能解決SSL握手錯誤?任何提示都很有用!我嘗試了很多我可以在谷歌上找到的東西,但目前爲止還沒有成功。

+0

另外檢查:http://stackoverflow.com/questions/29916962/javax-net-ssl-sslhandshakeexception-javax-net-ssl-sslprotocolexception-ssl-han – Chepech

回答

0

上有Android版本4.4.2一個已知的錯誤正在訪問HTTPS使用TLSv1.x協議時引起的。握手會失敗,因爲不支持TLS那麼HttpsURLConnection的回落到的SSLv3協議造成發生在握手的錯誤。我還沒有找到一個解決辦法,不涉及重新實現HttpsURLConnection的的TrustManagers防止錯誤或不安全的連接。

這是我做過什麼:

頻道自定義信任管理器到您的SSLContext:

// Trust manager that recognizes you acceptance criteria, that being ignoring handshake errors 
     ResourceTrustManager trustManager = new ResourceTrustManager(sslKeyStores); 
     TrustManager[] trustManagers = {trustManager}; 
     // use: org.apache.http.conn.ssl.AllowAllHostnameVerifier, this can be optional depending on your case. 
     AllowAllHostnameVerifier resourceHostNameVerifier = new AllowAllHostnameVerifier(); 

     // Install the trust manager and host name verifier 
     try { 
      SSLContext sc = SSLContext.getInstance("TLS"); 
      sc.init(null, trustManagers, new java.security.SecureRandom()); 
      HttpsURLConnection 
        .setDefaultSSLSocketFactory(sc.getSocketFactory()); 
      HttpsURLConnection.setDefaultHostnameVerifier(resourceHostNameVerifier); 
     } catch (Exception e) { 
      Log.e(TAG, "Invalid algorithm used while setting trust store:" +e.getMessage()); 
      throw e; 
     } 

要實現你的信任管理器只是簡單地覆蓋:

  • 公共無效checkClientTrusted
  • public void checkServerTrusted

礦使用本地密鑰庫嘗試授權證書:

public class ResourceTrustManager implements X509TrustManager { 

private static final String TAG = ResourceTrustManager.class.getName(); 
protected ArrayList<X509TrustManager> x509TrustManagers = new ArrayList<X509TrustManager>(); 

public ResourceTrustManager(Collection<KeyStore> additionalkeyStores) { 
    final List<TrustManagerFactory> factories = new ArrayList<TrustManagerFactory>(); 

    try { 
     /** 
     * Consolidates central and aditional keystore to be used as trust managers 
     */ 
     final TrustManagerFactory original = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); 
     original.init((KeyStore) null); 
     factories.add(original); 

     if(additionalkeyStores != null) { 
      for (KeyStore keyStore : additionalkeyStores) { 
       final TrustManagerFactory additionalCerts = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); 
       additionalCerts.init(keyStore); 
       factories.add(additionalCerts); 
      } 
     } 

    } catch (Exception e) { 
     throw new RuntimeException(e); 
    } 

    for (TrustManagerFactory tmf : factories) { 
     for (TrustManager tm : tmf.getTrustManagers()) { 
      if (tm instanceof X509TrustManager) { 
       x509TrustManagers.add((X509TrustManager) tm); 
      } 
     } 
    } 

    ResourceAssert.hasLength(x509TrustManagers, "Could not initialize with no trust managers"); 

} 

public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { 
    // The default Trustmanager with default keystore 
    final X509TrustManager defaultX509TrustManager = x509TrustManagers.get(0); 
    defaultX509TrustManager.checkClientTrusted(chain, authType); 

} 

public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { 
    for(X509TrustManager tm : x509TrustManagers) { 
     try { 
      tm.checkServerTrusted(chain,authType); 
      return; 
     } catch(CertificateException e) { 
      StringBuilder issuers = new StringBuilder(); 

      if(chain != null){ 
       for(X509Certificate cert :chain){ 
        issuers.append(" " +cert.getIssuerDN().getName()); 
       } 
      } 

      Log.e(TAG, "Untrusted host, connection is not secure "+ issuers + "\n\n" + e.getMessage()); 
     } 
    } 

} 

public X509Certificate[] getAcceptedIssuers() { 
    final ArrayList<X509Certificate> list = new ArrayList<X509Certificate>(); 

    for(X509TrustManager tm : x509TrustManagers) { 
     list.addAll(Arrays.asList(tm.getAcceptedIssuers())); 
    } 

    return list.toArray(new X509Certificate[list.size()]); 
} 


} 

這是不優雅可言,但能夠完成任務。

相關問題