2016-06-09 265 views
2

使用X509TrustManager檢查服務器是否可信時,我收到異常錯誤。我遵循開發人員的指示:https://developer.android.com/training/articles/security-ssl.html#UnknownCajava.security.cert.CertificateException:java.security.cert.CertPathValidatorException:未找到認證路徑的信任錨

我試圖拿出本地存儲在我的應用程序中的證書,並使用該證書與每個Volley API請求進行首次確認證書是可信的(已驗證) 。我從GoDaddy下載了證書並添加到我的項目中:https://certs.godaddy.com/repository/。確切的錯誤我得到的是以下情況:

06-09 15:01:20.509 10599-11180/com.app.debug W/System.err: java.security.cert.CertificateException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found. 
06-09 15:01:20.519 10599-11180/com.app.debug W/System.err:  at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:324) 
06-09 15:01:20.519 10599-11070/com.app.debug I/System.out: (HTTPLog)-Static: isSBSettingEnabled false 
06-09 15:01:20.519 10599-11180/com.app.debug W/System.err:  at com.android.org.conscrypt.TrustManagerImpl.checkServerTrusted(TrustManagerImpl.java:215) 
06-09 15:01:20.519 10599-11070/com.app.debug I/System.out: (HTTPLog)-Static: isSBSettingEnabled false 
06-09 15:01:20.519 10599-11180/com.app.debug W/System.err:  at com.udi.app.framework.net.VolleyClient$3.checkServerTrusted(SourceFile:170) 
06-09 15:01:20.519 10599-11180/com.app.debug W/System.err:  at com.android.org.conscrypt.Platform.checkServerTrusted(Platform.java:117) 
06-09 15:01:20.519 10599-11180/com.app.debug W/System.err:  at com.android.org.conscrypt.OpenSSLSocketImpl.verifyCertificateChain(OpenSSLSocketImpl.java:643) 
06-09 15:01:20.519 10599-11180/com.app.debug W/System.err:  at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method) 
06-09 15:01:20.519 10599-11180/com.app.debug W/System.err:  at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:353) 
06-09 15:01:20.519 10599-11180/com.app.debug W/System.err:  at com.android.okhttp.internal.http.SocketConnector.connectTls(SocketConnector.java:212) 
06-09 15:01:20.519 10599-11180/com.app.debug W/System.err:  at com.android.okhttp.Connection.connect(Connection.java:1322) 
06-09 15:01:20.519 10599-11180/com.app.debug W/System.err:  at com.android.okhttp.Connection.connectAndSetOwner(Connection.java:1410) 
06-09 15:01:20.519 10599-11180/com.app.debug W/System.err:  at com.android.okhttp.OkHttpClient$1.connectAndSetOwner(OkHttpClient.java:128) 
06-09 15:01:20.519 10599-11180/com.app.debug W/System.err:  at com.android.okhttp.internal.http.HttpEngine.nextConnection(HttpEngine.java:466) 
06-09 15:01:20.519 10599-11180/com.app.debug W/System.err:  at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:447) 
06-09 15:01:20.519 10599-11180/com.app.debug W/System.err:  at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:353) 
06-09 15:01:20.519 10599-11180/com.app.debug W/System.err:  at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:468) 
06-09 15:01:20.519 10599-11180/com.app.debug W/System.err:  at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:410) 
06-09 15:01:20.519 10599-11180/com.app.debug W/System.err:  at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:532) 
06-09 15:01:20.519 10599-11180/com.app.debug W/System.err:  at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.getResponseCode(DelegatingHttpsURLConnection.java:105) 
06-09 15:01:20.519 10599-11180/com.app.debug W/System.err:  at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:25) 
06-09 15:01:20.519 10599-11180/com.app.debug W/System.err:  at com.android.volley.toolbox.HurlStack.performRequest(SourceFile:109) 
06-09 15:01:20.519 10599-11180/com.app.debug W/System.err:  at com.android.volley.toolbox.BasicNetwork.performRequest(SourceFile:93) 
06-09 15:01:20.519 10599-11180/com.app.debug W/System.err:  at com.android.volley.NetworkDispatcher.run(SourceFile:105) 
06-09 15:01:20.519 10599-11180/com.app.debug W/System.err: Caused by: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found. 
06-09 15:01:20.519 10599-11180/com.app.debug W/System.err: ... 22 more 

我有一個名爲「VolleyClient」一流的管理所有我通過凌空發出請求。這是我的實現。我首先通過使用我的Volley請求隊列傳遞HurlStack對象。

HurlStack hurlStack = new HurlStack() { 
       @Override 
       protected HttpURLConnection createConnection(URL url) throws IOException { 
        HttpsURLConnection httpsURLConnection = (HttpsURLConnection) super.createConnection(url); 
        try { 
         httpsURLConnection.setSSLSocketFactory(getSSLSocketFactory()); 
         httpsURLConnection.setHostnameVerifier(getHostnameVerifier()); 
        } catch (Exception e) { 
         e.printStackTrace(); 
        } 
        return httpsURLConnection; 
       } 
      }; 

RequestQueue mRequestQueue = Volley.newRequestQueue(mContext.getApplicationContext(), hurlStack); 

我有一個主機名驗證

/** 
* This is used to verify local host. Let's assume the app is hosted inside of a server 
* machine which has a server certificate in which "Issued to" is "localhost", then 
* this method will verify "localhost". If not, can temporarily return true 
* @return 
*/ 
private HostnameVerifier getHostnameVerifier() { 
    return new HostnameVerifier() { 
     @Override 
     public boolean verify(String hostname, SSLSession session) { 
      //return true; 
      HostnameVerifier hv = HttpsURLConnection.getDefaultHostnameVerifier(); 
      return hv.verify("localhost", session); 
     } 
    }; 
} 

private SSLSocketFactory getSSLSocketFactory() 
     throws CertificateException, KeyStoreException, IOException, NoSuchAlgorithmException, KeyManagementException { 

    InputStream caInput = mContext.getResources().openRawResource(R.raw.gdig2); // this certificate file stored in \app\src\main\res\raw folder path 
    // From https://www.washington.edu/itconnect/security/ca/load-der.crt 
    //InputStream caInput = new BufferedInputStream(new FileInputStream("load-der.crt")); 
    CertificateFactory cf = null; 
    Certificate ca = null; 
    try { 
     cf = CertificateFactory.getInstance("X.509", "BC"); 
     ca = cf.generateCertificate(caInput); 
     System.out.println("ca=" + ((X509Certificate) ca).getSubjectDN()); 
    } catch (NoSuchProviderException e) { 
     e.printStackTrace(); 
    } finally { 
     caInput.close(); 
    } 
    caInput.close(); 

    // Create a KeyStore containing our trusted CAs 
    String keyStoreType = KeyStore.getDefaultType(); 
    KeyStore keyStore = KeyStore.getInstance(keyStoreType); //KeyStore keyStore = KeyStore.getInstance("BKS"); 
    keyStore.load(null, null); 
    keyStore.setCertificateEntry("ca", ca); 

    // Create a TrustManager that trusts the CAs in our KeyStore 
    String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm(); 
    TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm); 
    tmf.init(keyStore); 

    TrustManager[] wrappedTrustManagers = getWrappedTrustManagers(tmf.getTrustManagers()); 

    // Create an SSLContext that uses our TrustManager 
    SSLContext sslContext = SSLContext.getInstance("TLS"); 
    sslContext.init(null, wrappedTrustManagers, null); 

    return sslContext.getSocketFactory(); 
} 

private TrustManager[] getWrappedTrustManagers(TrustManager[] trustManagers) { 
    final X509TrustManager originalTrustManager = (X509TrustManager) trustManagers[0]; 
    return new TrustManager[]{ 
      new X509TrustManager() { 
       public X509Certificate[] getAcceptedIssuers() { 
        return originalTrustManager.getAcceptedIssuers(); 
       } 

       public void checkClientTrusted(X509Certificate[] certs, String authType) { 
        try { 
         originalTrustManager.checkClientTrusted(certs, authType); 
        } catch (CertificateException e) { 
         e.printStackTrace(); 
        } 
       } 

       public void checkServerTrusted(X509Certificate[] certs, String authType) { 
        try { 
         originalTrustManager.checkServerTrusted(certs, authType); 
        } catch (CertificateException e) { 
         // THIS IS THE EXCEPTION I GET WITH EACH REQUEST MADE 
         e.printStackTrace(); 
        } 
       } 
      } 
    }; 
} 

提前感謝!

編輯:這個例外發生在撥打穀歌時,因爲我使用谷歌地圖。此調用不使用來自我的服務器的已驗證證書,因此會導致證書路徑未找到異常的信任錨。

我可以通過總是返回true來規避這種情況,但這是正確的嗎?我應該返回我的服務器域嗎?

private HostnameVerifier getHostnameVerifier() { 
    return new HostnameVerifier() { 
     @Override 
     public boolean verify(String hostname, SSLSession session) { 
      // instead should I return back hv.verify("https:myserver.com", session); 
      return true; 
     } 
    }; 
} 
+1

請使用我的新的更新答案在http://stackoverflow.com/questions/32673568/does-android-volley-support-ssl/32674422#32674422 – BNK

+1

此外,如果您在Android中使用的證書是相同的證書在Web服務,然後你可以使用「tmf.getTrustManagers」,而不是getWrapp ... – BNK

+0

@BNK你的答案是非常類似於我已經實現,但是,我仍然不確定返回什麼主機名。您評論說'驗證總是返回true,這可能會導致不安全的網絡流量,因爲信任TLS/SSL服務器證書的主機名錯誤'。這是否意味着我應該指定我的服務器主機名? – portfoliobuilder

回答

0

檢查系統時間。確保它是最新的。

+0

認真?? ?? – Damiano

+0

當然......你可以更新你的設備時間..它的工作.. –

+0

究竟是如何改變時間鑼,使不受信任的證書被信任?請說明。 – EJP

相關問題