我有一个场景,我必须将证书传递给我的服务器,然后服务器向我发送他的证书,我必须接受它才能访问服务器。我正在使用HttpURLConnection,没有任何问题。
但是,我最近遇到了HttpURLConnection问题。我使用的代码从HTTPS服务器检索图像。如果图像很小(<500kb),则不会出现任何问题。然而,有了更大的图像,我得到了这个:
javax.net.ssl.SSLProtocolException:读取错误:ssl = 0x3c97e8:SSL库失败,通常是协议错误
我正在互联网上阅读它,很多人说使用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
由于
答案 0 :(得分:2)
以下代码禁用HttpsUrlConnection的任何新实例的SSL证书检查:
https://gist.github.com/aembleton/889392
/**
* Disables the SSL certificate checking for new instances of {@link HttpsURLConnection} This has been created to
* aid testing on a local box, not for use on production.
*/
private static void disableSSLCertificateChecking() {
TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
return null;
}
@Override
public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
// Not implemented
}
@Override
public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
// Not implemented
}
} };
try {
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
} catch (KeyManagementException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
答案 1 :(得分:1)
不要只接受任何证书。 不要使用破坏安全性的自制SSLSocketFactory
。使用SDK中的SSLSocketFactory,并传递信任存储(包含服务器证书或颁发它的CA证书)和密钥库(包含客户端证书和私钥)。您可以使用this构造函数来实现此目的,JavaDoc详细介绍了如何创建密钥库。