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();
		}
	}

}
时间: 2024-08-04 00:29:39

HttpClient忽略用户证书验证的方法的相关文章

Retrofit+OKHttp忽略https证书验证

记录这个的原因,是因为很多时候,因为后台配置的证书不正确导致APP访问不到服务器数据,导致影响自身的开发进度.没几行代码,逻辑也清晰,所以下面就直接贴出工具类吧: 1 package huolongluo.yeshen.byw.injection.model; 2 3 import java.security.SecureRandom; 4 import java.security.cert.X509Certificate; 5 6 import javax.net.ssl.HostnameVe

ThinkPHP中利用SESSION实现用户登录验证的方法

用户登上一个主页无非有这么两种状态,一种是类似于游客的身份登录,另一种是曾经已经登陆过的身份即经过服务器验证过的身份登录. 针对这两种登录,主要说一下: 我们在使用thinkphp的时候,首先,他是不提高登录验证功能的,仅仅是在路径方面做的相对比较安全,因为我们如果不对登录身份进行充足的验证,用户就完全可以去试着登录你的后台管理,那么这是非常可怕的,所以,首先要明白一个非常重要的业务逻辑. 如果按照正常的输入用户名密码的方式进行登录,在跳转之前我们就应该写入session数据,然后用数据进行登录

java httpclient 跳过证书验证

import java.io.IOException;import java.net.InetAddress;import java.net.Socket;import java.net.UnknownHostException; import javax.net.ssl.SSLContext;import javax.net.ssl.TrustManager; import org.apache.commons.httpclient.ConnectTimeoutException;import

python2/3 https忽略ssl证书验证

import ssl ssl._create_default_https_context = ssl._create_unverified_context InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised

iOS UIWebView 访问https绕过证书验证的方法

@implementation NSURLRequest (NSURLRequestWithIgnoreSSL) + (BOOL)allowsAnyHTTPSCertificateForHost:(NSString *)host{    return YES;} @end

HTTPS请求 SSL证书验证

import urllib2 url = "https://www.12306.cn/mormhweb/" headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"} request = urllib2.Request(ur

【转】MVC4验证用户登录特性实现方法

在开发过程中,需要用户登陆才能访问指定的页面这种功能,微软已经提供了这个特性. // 摘要: // 表示一个特性,该特性用于限制调用方对操作方法的访问. [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)] public class AuthorizeAttribute : FilterAttribute, IAuthorizationF

在HTTPS环境下使用NSURLSession,证书验证无法通过

调试信息: 测试环境是SSL3.0/TLS1.0,证书是通过Verisign颁发的 错误信息是:9846, An ssl error has occurred and a secure connection to the server cannot be made 实现了“NSURLSession:didReceiveChallenge:completionHandler”, 并使用“completionHandler(NSURLSessionAuthChallengePerformDefaul

配置Exchange 2013手机登录使用证书验证(Certificate-Based Authentication)

我们都知道默认情况下Exchange 2013服务器的移动设备连接服务器使用的是SSL基本身份验证. 需求描述: 今天有人提出,需要将Exchange 2013的手机连接认证方式使用证书来验证.如果手机客户端没有用户证书则不运行登陆邮箱. 优势: 配置使用证书验证的优点在于,手机客户端和服务器之间使用用户证书进行验证,当更改或重置用户密码时,不影响手机端用户的邮件服务,不会提示在更改密码后重新输入密码. 注意事项: 1.手机客户端使用的用户证书的Subject Name必须为该用户的User P