HttpClient忽略使用者證書驗證的方法
阿新 • • 發佈:2018-12-18
程式中出了這樣的異常:javax.net.ssl.SSLException: hostname in certificate didn't match。異常發生在這行程式碼上:httpClient.execute(httpGet); 初步判斷是證書的問題,準備採用忽略證書的方法解決,但在網上找了半天都沒找到靠譜的程式碼解決,最後還是自己琢磨解決了。 得到一個教訓,網上找答案是不靠譜的,因為具體問題需要具體分析,別人的方法不一定能解決你的,一定要自己思考,自己琢磨。在網上最重要的是能找到問題的解決思路,最後還是要自己去思考解決自己問題的具體程式碼實現。 最後吐槽一句,網上的解決方法大多都是廢話一籮筐,半天說不到核心解決方法上。
核心思路:繼承SSLSocketFactory,重寫一個驗證證書時總是返回true的UnVerifySocketFactory, * new一個這樣的UnVerifySocketFactory物件設定到httpclient上就行了.程式碼如下:
- import java.io.IOException;
- import java.net.Socket;
- import java.net.UnknownHostException;
- import java.security.KeyManagementException;
- import java.security.KeyStore;
- import java.security.KeyStoreException;
- import java.security.NoSuchAlgorithmException;
- import java.security.UnrecoverableKeyException;
- import java.security.cert.CertificateException;
- import java.security.cert.X509Certificate;
- import javax.net.ssl.SSLContext;
- import javax.net.ssl.SSLException;
- import javax.net.ssl.SSLSession;
- import javax.net.ssl.SSLSocket;
- import javax.net.ssl.TrustManager;
- import javax.net.ssl.X509TrustManager;
- import org.apache.http.HttpVersion;
- import org.apache.http.client.HttpClient;
- import org.apache.http.conn.ClientConnectionManager;
- import org.apache.http.conn.scheme.PlainSocketFactory;
- import org.apache.http.conn.scheme.Scheme;
- import org.apache.http.conn.scheme.SchemeRegistry;
- import org.apache.http.conn.ssl.SSLSocketFactory;
- import org.apache.http.conn.ssl.X509HostnameVerifier;
- import org.apache.http.impl.client.DefaultHttpClient;
- import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
- import org.apache.http.params.BasicHttpParams;
- import org.apache.http.params.HttpParams;
- import org.apache.http.params.HttpProtocolParams;
- import org.apache.http.protocol.HTTP;
- import android.util.Log;
- /**
- * 工具類:建立一個忽略使用者證書驗證的httpClient例項
- * @date 2015-02-13
- * @author Barry
- */
- public class CertificateValidationIgnored {
- public static HttpClient getNoCertificateHttpClient(String url){
- return getCertificateValidationIgnoredHttpClient();
- }
- private static HttpClient getCertificateValidationIgnoredHttpClient() {
- try {
- KeyStore trustStore = KeyStore.getInstance(KeyStore
- .getDefaultType());
- trustStore.load(null, null);
- //核心程式碼,建立一個UnVerifySocketFactory物件,驗證證書時總是返回true
- SSLSocketFactory sf = new UnVerifySocketFactory(trustStore);
- 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("http", PlainSocketFactory
- .getSocketFactory(), 80));
- registry.register(new Scheme("https", sf, 443));
- ClientConnectionManager ccm = new ThreadSafeClientConnManager(
- params, registry);
- return new DefaultHttpClient(ccm, params);
- } catch (Exception e) {
- Log.d("CertificateValidationIgnored", "建立忽略使用者證書的HttpClient物件失敗,嘗試建立普通HttpClient物件");
- e.printStackTrace();
- return new DefaultHttpClient();
- }
- }
- /**
- * 核心類
- * UnVerifySocketFactory:一個驗證證書時總是返回true的SSLSocketFactory的子類
- */
- private static X509HostnameVerifier ignoreVerifier;
- private static class UnVerifySocketFactory extends SSLSocketFactory {
- SSLContext sslContext = SSLContext.getInstance("TLS");
- public UnVerifySocketFactory(KeyStore truststore)
- throws NoSuchAlgorithmException, KeyManagementException,
- KeyStoreException, UnrecoverableKeyException {
- super(truststore);
- TrustManager tm = new X509TrustManager() {
- public void checkClientTrusted(X509Certificate[] chain,
- String authType) throws CertificateException {
- }
- public void checkServerTrusted(X509Certificate[] chain,
- String authType) throws CertificateException {
- }
- public X509Certificate[] getAcceptedIssuers() {
- return null;
- }
- };
- sslContext.init(null, new TrustManager[] { tm }, null);
- }
- @Override
- public Socket createSocket(Socket socket, String host, int port,
- boolean autoClose) throws IOException, UnknownHostException {
- return sslContext.getSocketFactory().createSocket(socket, host,
- port, autoClose);
- }
- //核心程式碼
- @Override
- public void setHostnameVerifier(X509HostnameVerifier hostnameVerifier) {
- // TODO Auto-generated method stub
- ignoreVerifier = new X509HostnameVerifier() {
- @Override
- public void verify(String arg0, String[] arg1, String[] arg2)
- throws SSLException {
- }
- @Override
- public void verify(String arg0, X509Certificate arg1)
- throws SSLException {
- }
- @Override
- public void verify(String arg0, SSLSocket arg1)
- throws IOException {
- }
- //最最核心程式碼
- @Override
- public boolean verify(String arg0, SSLSession arg1) {
- return true;
- }
- };
- super.setHostnameVerifier(ignoreVerifier);
- }
- @Override
- public X509HostnameVerifier getHostnameVerifier() {
- return ignoreVerifier;
- }
- @Override
- public Socket createSocket() throws IOException {
- return sslContext.getSocketFactory().createSocket();
- }
- }
- }