Android:Https跳过证书验证、Https使用证书、HttpClient、

在公司用习惯了Http请求,突然要用到Https请求,因为突然换了我太不习惯,在第三方网络请求发现无用时,我开始使用原生的网络请求,突然发现完全不会Https请求。结果一段时间的总结与使用,我把这期间的使用心得发布到csdn,为了是总结知识点和广大程序猿方便。


既然叫跳过证书验证,那么我们在使用网络请求之前,就应该使用一定的手段来跳过验证。

1、首先得重写org.apache.http.conn.ssl.SSLSocketFactory这个类,从字面意思理解就是:加密套接字协议层工厂。
2、必须用到TrustManager 就是证书管理者。
3、最后就是要用到安全协议的实现类:SSLContext

接下来就一步一步完成。

1、直接继承SSLSocketFactory

public class SSLHttpsUtils extends SSLSocketFactory{

	/**
	 * @param truststore
	 * @throws NoSuchAlgorithmException
	 * @throws KeyManagementException
	 * @throws KeyStoreException
	 * @throws UnrecoverableKeyException
	 */
	public SSLHttpsUtils(KeyStore truststore) throws NoSuchAlgorithmException,
			KeyManagementException, KeyStoreException,
			UnrecoverableKeyException {
		super(truststore);
	}
}

2、通过官方API发现原来TrustManager里面没有任何内容,只有一个间接子类X509TrustManager,通过网上查看,X509是一个通用的证书格式,只需要拿到这个一个格式就OK了。

TrustManager manager = new X509TrustManager() {
		
		@Override
		public X509Certificate[] getAcceptedIssuers() {
			// TODO Auto-generated method stub
			return null;
		}
		@Override
		public void checkServerTrusted(X509Certificate[] arg0, String arg1)
				throws CertificateException {
			// TODO Auto-generated method stub	
		}
		@Override
		public void checkClientTrusted(X509Certificate[] arg0, String arg1)
				throws CertificateException {
			// TODO Auto-generated method stub	
		}
	};

3、最后把这些东西融合到一起就要用到SSLContext,通过API发现通过SSLContext.getInstance,这里我们就取最简单的,里面传参发现一个不认识的参数通过查找是一个指定的安全协议:TLS三次握手协议,最后通过init初始化这个安全协议,再把这个方法放在SSLSocketFactory的构造函数中。

<pre name="code" class="java">private SSLContext context = SSLContext.getInstance("TLS");

	private void initSSLContext() {
		try {
			// 既然是跳过认证,我们把没有的都填null,此时发现第二个参数是一个数组,那么意思就是我们可以放多个证书认证;
			context.init(null, new TrustManager[] { manager }, null);
		} catch (KeyManagementException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}


 

4、以上工作做完我们就开始使用这些东西,并得到我们想要的。

public static DefaultHttpClient getNewHttpClient() {
		try {
			// 查看API这里可以得到一个默认的Type.
			KeyStore truststore = KeyStore.getInstance(KeyStore.getDefaultType());
			// 这里发现需要一个KeyStore,那么我们就在上面New一个KeyStore,这是一个密钥库,查看API发现能直接getInstance得到对象;
			SSLSocketFactory factory = new SSLHttpsUtils(truststore);
			// 这里就是我们最需要的也是最关键的一步,设置主机认证,通过API发现有一个常量就是允许所有认证通过。
			factory.setHostnameVerifier(ALLOW_ALL_HOSTNAME_VERIFIER);

			// 实现Httpprams的子类
			HttpParams params = new BasicHttpParams();
			//通过Http适配器设置必要参数,现在通用HTTP1.1协议,和UTF-8字符。
			HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
			HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);
			//通过适配器设置连接参数,等待时间和,连接时间
			HttpConnectionParams.setSoTimeout(params, 10000);
			HttpConnectionParams.setConnectionTimeout(params, 5000);
			
			// 同样New出来,查看API,需要我们注册一个计划,来封装协议细节
			SchemeRegistry schreg = new SchemeRegistry();
			// 最后一个参数是端口设置,Https常用的端口就是443。
			schreg.register(new Scheme("https", factory, 443));
			// 既然是工具类,这里也把http协议加上,中间的协议工厂我们就用简单的PlainSocketFactory,这里可以通过API查看到,端口就用常用的80端口(默认)
			schreg.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
			
			// ClientConnectionManager是一个借口,就实现他的子类,同样需要2个参数,第一个我们熟悉,第二个就是让我们自定义自己的一套方案协议,继续在上面一步一步完成;
			ClientConnectionManager conman = new SingleClientConnManager(params, schreg);
			
			// 返回我们需要的一个默认Httpclient,为了把之前做的关联起来,就new最多参数的构造函数,需要2个参数,Httpparams是我们熟悉的,
			// 发现ClientConnectionManager不太熟悉,通过API发现这是客服端连接管理者,既然这样,就在上面一步一步完成。
			return new DefaultHttpClient(conman, params);
		} catch (Exception e) {
			// TODO: handle exception
		}
		return new DefaultHttpClient();
	}

很多东西我是通过倒推查看API来完成的,如果没看懂,可以先通看一次,然后再倒推回去看。

最后附上完整代码:

/**
 * @author 李飞翔
 * @ SSLHttpsUtils.java
 * 时间:2016-1-11 下午8:03:05
 *
 */
package com.example.boketestapplication;

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.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.http.HttpVersion;
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.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.SingleClientConnManager;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
import org.apache.http.protocol.HTTP;

/**
 * @author 李飞翔
 * @name SSLHttpsUtils.java
 * @data 2016-1-11 下午8:03:05
 * @TODO
 */
public class SSLHttpsUtils extends SSLSocketFactory {

	/**
	 * @param truststore
	 * @throws NoSuchAlgorithmException
	 * @throws KeyManagementException
	 * @throws KeyStoreException
	 * @throws UnrecoverableKeyException
	 */
	public SSLHttpsUtils(KeyStore truststore) throws NoSuchAlgorithmException,
			KeyManagementException, KeyStoreException,
			UnrecoverableKeyException {
		super(truststore);
		initSSLContext();
	}

	TrustManager manager = new X509TrustManager() {

		@Override
		public X509Certificate[] getAcceptedIssuers() {
			// TODO Auto-generated method stub
			return null;
		}

		@Override
		public void checkServerTrusted(X509Certificate[] arg0, String arg1)
				throws CertificateException {
			// TODO Auto-generated method stub

		}

		@Override
		public void checkClientTrusted(X509Certificate[] arg0, String arg1)
				throws CertificateException {
			// TODO Auto-generated method stub

		}
	};
	private SSLContext context = SSLContext.getInstance("TLS");

	private void initSSLContext() {
		try {
			// 既然是跳过认证,我们把没有的都填null,此时发现第二个参数是一个数组,那么意思就是我们可以放多个证书认证;
			context.init(null, new TrustManager[] { manager }, null);
		} catch (KeyManagementException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public static DefaultHttpClient getNewHttpClient() {
		try {
			// 查看API这里可以得到一个默认的Type.
			KeyStore truststore = KeyStore.getInstance(KeyStore
					.getDefaultType());
			// 这里发现需要一个KeyStore,那么我们就在上面New一个KeyStore,这是一个密钥库,查看API发现能直接getInstance得到对象;
			SSLSocketFactory factory = new SSLHttpsUtils(truststore);
			// 这里就是我们最需要的也是最关键的一步,设置主机认证,通过API发现有一个常量就是允许所有认证通过。
			factory.setHostnameVerifier(ALLOW_ALL_HOSTNAME_VERIFIER);

			// 实现Httpprams的子类
			HttpParams params = new BasicHttpParams();
			//通过Http适配器设置必要参数,现在通用HTTP1.1协议,和UTF-8字符。
			HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
			HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);
			//通过适配器设置连接参数,等待时间和,连接时间
			HttpConnectionParams.setSoTimeout(params, 10000);
			HttpConnectionParams.setConnectionTimeout(params, 5000);
			
			// 同样New出来,查看API,需要我们注册一个计划,来封装协议细节
			SchemeRegistry schreg = new SchemeRegistry();
			// 最后一个参数是端口设置,Https常用的端口就是443。
			schreg.register(new Scheme("https", factory, 443));
			// 既然是工具类,这里也把http协议加上,中间的协议工厂我们就用简单的PlainSocketFactory,这里可以通过API查看到,端口就用常用的80端口(默认)
			schreg.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
			
			// ClientConnectionManager是一个借口,就实现他的子类,同样需要2个参数,第一个我们熟悉,第二个就是让我们自定义自己的一套方案协议,继续在上面一步一步完成;
			ClientConnectionManager conman = new SingleClientConnManager(
					params, schreg);
			
			// 返回我们需要的一个默认Httpclient,为了把之前做的关联起来,就new最多参数的构造函数,需要2个参数,Httpparams是我们熟悉的,
			// 发现ClientConnectionManager不太熟悉,通过API发现这是客服端连接管理者,既然这样,就在上面一步一步完成。
			return new DefaultHttpClient(conman, params);
		} catch (Exception e) {
			// TODO: handle exception
		}
		return new DefaultHttpClient();
	}
}









  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

老李与GPT

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值