Android - 如何使用 HttpClient 接受任何证书并同时传递证书
我有一个场景,我必须将证书传递给我的服务器,然后服务器向我发送他的证书,我必须接受该证书才能访问服务器。我为此使用 HttpURLConnection ,没有任何问题。
但是,我最近遇到了 HttpURLConnection 的问题。我使用的代码从 HTTPS 服务器检索图像。如果图像很小(< 500kb),则不会出现任何问题。然而,对于较大的图像,我得到了这个:
javax.net.ssl.SSLProtocolException: Read error: ssl=0x3c97e8: Failure in SSL library, 通常是一个协议错误
我在互联网上读到了有关它的信息,很多人说使用 HttpClient 代替HttpURLConnection 是可行的方法(一个例子是这个网站 http://soan.tistory.com/62 ,认为这是用韩语写的,我看不懂,但我认为它就是这么说的)。
这是我的旧代码,使用 URLConnection:
public static URLConnection CreateFromP12(String uri, String keyFilePath,
String keyPass, TrustManager[] trustPolicy, HostnameVerifier hv) {
try {
SSLContext sslContext = SSLContext.getInstance("TLS");
KeyStore keyStore = KeyStore.getInstance("PKCS12");
KeyManagerFactory kmf = KeyManagerFactory.getInstance("X509");
keyStore.load(new FileInputStream(keyFilePath),
keyPass.toCharArray());
kmf.init(keyStore, keyPass.toCharArray());
sslContext.init(kmf.getKeyManagers(), trustPolicy, null);
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext
.getSocketFactory());
HttpsURLConnection.setDefaultHostnameVerifier(hv);
} catch (Exception ex) {
return null;
}
URL url;
URLConnection conn;
try {
url = new URL(uri);
conn = url.openConnection();
} catch (MalformedURLException e) {
return null;
} catch (IOException e) {
return null;
}
return conn;
}
这是新代码,使用 HttpClient:
public class HttpC2Connection {
public static HttpEntity CreateHttpEntityFromP12(String uri,
String keyFilePath, String keyPass) throws Exception {
KeyStore keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(new FileInputStream(keyFilePath), keyPass.toCharArray());
SSLSocketFactory sf = new MySSLSocketFactory(keyStore);
sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
HttpParams params = new BasicHttpParams();
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("https", sf, 443));
ClientConnectionManager ccm = new ThreadSafeClientConnManager(params,
registry);
HttpClient httpclient = new DefaultHttpClient(ccm, params);
HttpGet httpget = new HttpGet(uri);
HttpResponse response = httpclient.execute(httpget);
HttpEntity entity = response.getEntity();
return entity;
}
但现在,使用 HttpClient,我的服务器返回一个错误,说我必须通过证书,所以我猜这
SSLSocketFactory sf = new MySSLSocketFactory(keyStore);
没有加载我的证书。
那么,我怎样才能同时做以下两件事:
1.)将证书传递到我的服务器; 2.)
使用 HttpClient 类接受来自我的服务器的任何证书吗?
PS:我使用的是Android 3.0
谢谢
I have a scenario in which I must pass a certficate to my server, then the server sends me his certificate, which I must accept to access the server. I was using HttpURLConnection for this, with no problems.
However, I recently had a problem with HttpURLConnection. The code I was using retrieved an image from a HTTPS server. If the image was small (< 500kb), no problem whatsoever occured. However, with larger images I got this:
javax.net.ssl.SSLProtocolException: Read error: ssl=0x3c97e8: Failure in SSL library, usually a protocol error
I was reading about it on the Internet, and many people said that using HttpClient instead of HttpURLConnection was the way to go (an example is this site http://soan.tistory.com/62 , think that is written in korean, I can't read it but that's what I think it says).
This is my old code, using URLConnection:
public static URLConnection CreateFromP12(String uri, String keyFilePath,
String keyPass, TrustManager[] trustPolicy, HostnameVerifier hv) {
try {
SSLContext sslContext = SSLContext.getInstance("TLS");
KeyStore keyStore = KeyStore.getInstance("PKCS12");
KeyManagerFactory kmf = KeyManagerFactory.getInstance("X509");
keyStore.load(new FileInputStream(keyFilePath),
keyPass.toCharArray());
kmf.init(keyStore, keyPass.toCharArray());
sslContext.init(kmf.getKeyManagers(), trustPolicy, null);
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext
.getSocketFactory());
HttpsURLConnection.setDefaultHostnameVerifier(hv);
} catch (Exception ex) {
return null;
}
URL url;
URLConnection conn;
try {
url = new URL(uri);
conn = url.openConnection();
} catch (MalformedURLException e) {
return null;
} catch (IOException e) {
return null;
}
return conn;
}
And this is the new one, using HttpClient:
public class HttpC2Connection {
public static HttpEntity CreateHttpEntityFromP12(String uri,
String keyFilePath, String keyPass) throws Exception {
KeyStore keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(new FileInputStream(keyFilePath), keyPass.toCharArray());
SSLSocketFactory sf = new MySSLSocketFactory(keyStore);
sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
HttpParams params = new BasicHttpParams();
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("https", sf, 443));
ClientConnectionManager ccm = new ThreadSafeClientConnManager(params,
registry);
HttpClient httpclient = new DefaultHttpClient(ccm, params);
HttpGet httpget = new HttpGet(uri);
HttpResponse response = httpclient.execute(httpget);
HttpEntity entity = response.getEntity();
return entity;
}
But now, using HttpClient, my server returns me an error saying that I must pass a certificate, so I guess that
SSLSocketFactory sf = new MySSLSocketFactory(keyStore);
isn't loading my certificate.
So, how can I do the following two things at the same time:
1.) Pass a certificate to my server;
2.) Accept any certificate from my server
Using the HttpClient class?
PS: I'm using Android 3.0
Thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
以下代码禁用对任何新 HttpsUrlConnection 实例的 SSL 证书检查:
https://gist.github.com/aembleton /889392
The following code disables SSL certificate checking for any new instances of HttpsUrlConnection:
https://gist.github.com/aembleton/889392
不要只接受任何证书。 不要使用自制的会损害安全性的
SSLSocketFactory
。使用 SDK 中的 SSLSocketFactory 并传递信任存储(包含服务器证书或颁发它的 CA 证书)和密钥存储(包含您的客户端证书和私钥)。您可以使用 this 构造函数来实现这一点,JavaDoc 有关于如何创建密钥存储的详细信息。Don't just accept any certificates. Don't use home-made
SSLSocketFactory
's that compromise security. Use the SSLSocketFactory from the SDK, and pass both a trust store (containing the server certificate or the CA certificate that issued it) and a keystore (containing your client certificate and private key). You can use this constructor to achieve this, the JavaDoc has details on how to create the key stores.