HttpClient忽略用户证书验证的方法

    程序中出了这样的异常: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();
		}
	}
		
}


郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。