Решение - создать собственную фабрику сокетов.
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;
}
}
Затем создайте SSLContext, который использует ваш TrustManager, а затем создайте AndroidHttpClient и замените его схему https на схему, которая использует ваш SocketFactory.
/**
* 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» (два хранилища ключей). Затем вам не нужно пытаться добавить сертификаты в системный склад ключей. Вы можете создать свой собственный KeyStore в папке getFilesDir ().
У меня до сих пор нет законченной логики для захвата сертификата из HttpResult = HttpClient.execute (HttpPost); метод, но я сейчас активно пишу это. Если вам нужна помощь, я мог бы работать с вами сейчас.
Если кто-то знает, как перехватить / получить сертификат от SSLSocekt внутри объекта HttpRequestBase, пожалуйста, дайте мне знать. Я пытаюсь выследить это.