android上的HttpClient和自定义TrustManager
我一直在尝试向ApacheHttpClient库注册我的自定义TrustManger。以下链接包含有关如何执行此操作的说明: 不幸的是,我想要使用的构造函数(publicssslsocketfactory(sslcontextsslcontext))在HttpClient的Android版本中不可用。我将使用sslContext初始化我的自定义TrustManager。Android似乎已经用“密钥库”取代了这一功能 我的问题是:(如何)在Android中向DefaultHttpClient注册自定义TrustManager?在KeyStore类中是否有其他选择 最终我想暂时忽略证书检查。。。android上的HttpClient和自定义TrustManager,android,ssl,httpclient,Android,Ssl,Httpclient,我一直在尝试向ApacheHttpClient库注册我的自定义TrustManger。以下链接包含有关如何执行此操作的说明: 不幸的是,我想要使用的构造函数(publicssslsocketfactory(sslcontextsslcontext))在HttpClient的Android版本中不可用。我将使用sslContext初始化我的自定义TrustManager。Android似乎已经用“密钥库”取代了这一功能 我的问题是:(如何)在Android中向DefaultHttpClient注册
请只考虑我的整个应用程序是基于它的HtpPosiver库。 < P>解决方案是创建自己的套接字工厂。
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,并将其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;
}
如果您不知道如何创建新的密钥库,请执行以下操作:
/**
* 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;
}
/**
*获取当前密钥库,如果尚未创建,则创建一个新密钥库。这
*不会加载由标识的密钥库文件
*{@link#密钥库_NAME}。要加载密钥库文件,请使用函数
*{@link#loadKeyStore()}将自动调用此函数(因此
*你不需要)。
*
*
*@返回一个{@link KeyStore}
*/
公共密钥库getKeyStore(){
if(mKeyStore!=null)
返回mKeyStore;
试一试{
字符串defaultType=KeyStore.getDefaultType();
mKeyStore=KeyStore.getInstance(defaultType);
mKeyStore.load(null,null);
}捕获(例外e){
Log.w(标记,e.getMessage());
}
返回mKeyStore;
}
上述解决方案是一个解决方案的开始,该解决方案允许您创建一个TrustManager,以验证“系统密钥库”以及您自己的“私有密钥库”(两个密钥库)的证书。然后,您不需要尝试向系统密钥库添加证书。您可以在getFilesDir()文件夹中创建自己的密钥库
我仍然没有完成捕获来自HttpResult=HttpClient.execute(HttpPost)的证书的逻辑;方法,但我现在正在积极地写这篇文章。如果你需要帮助,我现在也许可以和你一起做这件事
如果有人知道如何从HttpRequestBase对象中的SSLSocket捕获/获取证书,请告诉我。我正试图找到它。实际上,该方法存在,但被隐藏。它由getHttpSocketFactory()在内部使用。我通过简单地使用反射来实现它。在一段时间内不安全,但出于开发目的可以
Class<org.apache.http.conn.ssl.SSLSocketFactory> c = org.apache.http.conn.ssl.SSLSocketFactory.class;
Constructor<org.apache.http.conn.ssl.SSLSocketFactory> ctor = c.getConstructor(javax.net.ssl.SSLSocketFactory.class);
SSLSocketFactory ssf = ctor.newInstance(SSLCertificateSocketFactory.getInsecure(getSSLHandshakeTimeout(), null));
Class c=org.apache.http.conn.ssl.SSLSocketFactory.Class;
Constructor=c.getConstructor(javax.net.ssl.SSLSocketFactory.class);
SSLSocketFactory ssf=ctor.newInstance(SSLCertificateSocketFactory.getUnsecure(getSSLHandshakeTimeout(),null));
安装自定义TrustManager的全部原因是为了避免证书检查。经过一周的博客、java代码和android源代码研究,发现问题实际上在于我连接的站点上ssl证书的排序。因此,如果您遇到证书验证问题,请始终仔细检查证书是否以正确的顺序提供给您,以及根证书是否存在于android设备上!我仍然对这个问题的答案感兴趣,我自己…@ivo我想我也有一个坏了的证书的问题!你做了什么来解决这个问题?你做过某种排序吗?@elton我让网站管理员重新排序证书,一切都很好。证书的顺序很容易检查,在一个我现在记不起名字的博客中有描述……从SSLSocket获得证书成功了吗?
Class<org.apache.http.conn.ssl.SSLSocketFactory> c = org.apache.http.conn.ssl.SSLSocketFactory.class;
Constructor<org.apache.http.conn.ssl.SSLSocketFactory> ctor = c.getConstructor(javax.net.ssl.SSLSocketFactory.class);
SSLSocketFactory ssf = ctor.newInstance(SSLCertificateSocketFactory.getInsecure(getSSLHandshakeTimeout(), null));