解決方案是創建自己的套接字工廠。
public class NetworkSSLSocketFactory implements LayeredSocketFactory {
private SSLContext sslContext;
private SSLSocketFactory socketFactory;
private X509HostnameVerifier hostnameVerifier;
/**
* Creates a socket factory that will use the {@link SSLContext} and
* {@link X509HostnameVerifier} specified. The SSLContext provided should
* have the {@link NetworkTrustManager} associated with it.
*
* @param sslContext
* @param hostnameVerifier
*/
public NetworkSSLSocketFactory(SSLContext sslContext,
X509HostnameVerifier hostnameVerifier) {
this.sslContext = sslContext;
this.socketFactory = sslContext.getSocketFactory();
this.hostnameVerifier = hostnameVerifier;
}
}
然後創建一個使用TrustManager的SSLContext中,然後創建一個AndroidHttpClient,並使用您的SocketFactory一個替換其HTTPS模式。
/**
* Return the SSLContext for use with our HttpClient or create a new Context
* if needed.
* <p>
* This context uses our {@link NetworkTrustManager}
*
* @return an {@link SSLContext}
*/
public SSLContext getSSLContext() {
if (mSSLContextInstance != null)
return mSSLContextInstance;
try {
mSSLContextInstance = SSLContext.getInstance("TLS");
TrustManager trustManager = new NetworkTrustManager(getKeyStore());
TrustManager[] tms = new TrustManager[] { trustManager };
mSSLContextInstance.init(null, tms, new SecureRandom());
} catch (NoSuchAlgorithmException e) {
Log.e(TAG, e.getMessage());
} catch (KeyManagementException e) {
Log.e(TAG, e.getMessage());
}
return mSSLContextInstance;
}
現在客戶
/**
* Return an HttpClient using our {@link NetworkTrustManager} and
* {@link NetworkHostnameVerifier}
*
* @return an {@link HttpClient}
*/
public HttpClient getHttpClient() {
if (mHttpClientInstance != null)
return mHttpClientInstance;
SSLContext sslContext = getSSLContext();
// Now create our socket factory using our context.
X509HostnameVerifier hostnameVerifier = new NetworkHostnameVerifier();
NetworkSSLSocketFactory sslSocketFactory = new NetworkSSLSocketFactory(
sslContext, hostnameVerifier);
// Some services (like the KSOAP client) use the HttpsURLConnection
// class
// to establish SSL connections.
HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext
.getSocketFactory());
// Generate the Client for the Server
mHttpClientInstance = AndroidHttpClient.newInstance(getAgent(),
mContext);
// Get the registry from the AndroidHttpClient and change the
// HTTPS scheme to use our socket factory. This way we can
// control the certificate authority and trust system.
SchemeRegistry schemeRegistry = mHttpClientInstance
.getConnectionManager().getSchemeRegistry();
schemeRegistry.register(new Scheme("https", sslSocketFactory, 443));
return mHttpClientInstance;
}
如果你不知道如何創建一個新的密鑰庫,在這裏你去:
/**
* Get the current KeyStore or if not yet created, create a new one. This
* will <b>NOT</b> load the KeyStore file identified by
* {@link #KEYSTORE_NAME}. To load the KeyStore file, use the function
* {@link #loadKeyStore()} which will automatically call this function (so
* you don't need to).
* <p>
*
* @return a {@link KeyStore}
*/
public KeyStore getKeyStore() {
if (mKeyStore != null)
return mKeyStore;
try {
String defaultType = KeyStore.getDefaultType();
mKeyStore = KeyStore.getInstance(defaultType);
mKeyStore.load(null, null);
} catch (Exception e) {
Log.w(TAG, e.getMessage());
}
return mKeyStore;
}
上述解決方案是一個解決方案的開始它允許您創建一個TrustManager,它將驗證「System KeyStore」以及您擁有的「Private KeyStore」(兩個密鑰庫)的證書。然後,您不需要嘗試將證書添加到System KeyStore。您可以在getFilesDir()文件夾中創建自己的KeyStore。
我仍然沒有完成從HttpResult = HttpClient.execute(HttpPost)陷阱證書的邏輯;方法,但我現在正在積極撰寫此文。如果你需要幫助,我現在可以和你一起工作。
如果有人知道如何從HttpRequestBase對象中的SSLSocekt陷阱/獲取證書,請告訴我。我試圖追捕這件事。
安裝自定義TrustManager的全部原因是爲了避免證書檢查。在看了博客,java代碼和android資源一週後,結果發現問題實際上是我連接的網站上的SSL證書的順序。因此,如果遇到證書驗證問題,請始終仔細檢查證書是否以正確的順序呈現給您,並且根證書是否存在於Android設備上! – Ivo 2011-03-04 10:34:12
我仍然對這個問題的答案感興趣,我自己... – Cephron 2011-03-21 15:22:34
@ivo我認爲我也有一個無序的證書問題!你做了什麼來解決這個問題?你做一些排序? – 2011-10-21 10:07:19