网上大多数多Https的处理都是忽略所有证书的校验,大致做法如下:
private void TrustAllHttps() {
try {
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, new TrustManager[] { new TrustAllManager() }, new SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
HttpsURLConnection.setDefaultHostnameVerifier(new TrustHostnameVerifier());
HttpsURLConnection conn = (HttpsURLConnection) new URL(URL_TEST).openConnection();
conn.setRequestMethod("POST");// 设置请求类型为post
conn.setDoOutput(true);
conn.setDoInput(true);
conn.connect();
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
StringBuffer sb = new StringBuffer();
String line;
while ((line = br.readLine()) != null) {
sb.append(line);
Log.d("TAG", line);
}
} catch (Exception e) {
Log.e(this.getClass().getName(), e.getMessage());
}
}
private class TrustHostnameVerifier implements HostnameVerifier {
// 信任所有主机-对于任何证书都不做检查
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
}
private class TrustAllManager implements X509TrustManager {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
}
之前我们也是这么做的,但是存在风险,最近改为单向验证,参考了网上的各种写法,代码如下(都写在一块了,最好自己调整下):
/**
* HttpsUrlConnection 方式,支持指定**.crt证书验证,此种方式Android官方建议
*
* @throws CertificateException
* @throws IOException
* @throws KeyStoreException
* @throws NoSuchAlgorithmException
* @throws KeyManagementException
* @throws NoSuchProviderException
*/
public void initHttpsConnection() {
try {
InputStream in = getAssets().open("server.cer");
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
Certificate cer = certificateFactory.generateCertificate(in);
System.out.println("ca=" + ((X509Certificate) cer).getSubjectDN());
// Create a KeyStore containing our trusted CAs
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
keystore.load(null);
keystore.setCertificateEntry("ca", cer);
// Create a TrustManager that trusts the CAs in our KeyStore
String algorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(algorithm);
trustManagerFactory.init(keystore);
// Create an SSLContext that uses our TrustManager
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, trustManagerFactory.getTrustManagers(), null);
URL url = new URL(URL);
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
conn.setSSLSocketFactory(sslContext.getSocketFactory());
conn.setHostnameVerifier(DO_NOT_VERIFY);
conn.setRequestMethod("POST");// 设置请求类型为post
conn.setConnectTimeout(10000);// 设置超时时间
conn.setReadTimeout(50000);
conn.setDoInput(true);
conn.setDoOutput(true);
InputStream input = conn.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input));
StringBuffer result = new StringBuffer();
String line;
while ((line = reader.readLine()) != null) {
result.append(line);
Log.d("TAG", line);
}
} catch (Exception e) {
Log.e(this.getClass().getName(), e.getMessage());
}
}
static HostnameVerifier DO_NOT_VERIFY = new HostnameVerifier() {
// 信任所有主机
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
代码基于HttpsURLConnection实现,其他方式也都差不多。