使用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;
}
};
}
請使用我的新的更新答案在http://stackoverflow.com/questions/32673568/does-android-volley-support-ssl/32674422#32674422 – BNK
此外,如果您在Android中使用的證書是相同的證書在Web服務,然後你可以使用「tmf.getTrustManagers」,而不是getWrapp ... – BNK
@BNK你的答案是非常類似於我已經實現,但是,我仍然不確定返回什麼主機名。您評論說'驗證總是返回true,這可能會導致不安全的網絡流量,因爲信任TLS/SSL服務器證書的主機名錯誤'。這是否意味着我應該指定我的服務器主機名? – portfoliobuilder