基于HttpClient 4.3的可訪问自签名HTTPS网站的新版工具类

本文出处:http://blog.csdn.net/chaijunkun/article/details/40145685,转载请注明。因为本人不定期会整理相关博文,会对相应内容作出完好。因此强烈建议在原始出处查看此文。

HttpClient在当今Java应用中的位置越来越重要。从该项目的变迁过程我们不难发现,其已经从apache-commons众多的子项目中剥离,一跃成为现在的顶级项目。可见它的分量。然而随着项目的升级和架构的调整。非常多曾经经常使用的类和方法都已被打上了@Deprecated注解,作为一个有代码洁癖的程序员。我们也有必要升级一下工具类,让代码更加整洁。

另外在项目中正好须要訪问https协议的接口。而相应的server没有购买商业CA颁发的正式受信证书,仅仅是做了个自签名(联想一下12306站点购票时提示的那个警告信息)。默认情况下通过HttpClient訪问会抛出异常,在本文中也给出了解决的方法。

在HttpClient 4.x版本号中引入了大量的构造器设计模式。非常多的配置都不建议直接new出来。并且相关的API也有所修改,比如连接參数,曾经是直接new出HttpConnectionParams对象后通过set方法逐一设置属性,现在有了构造器。能够通过例如以下方式进行构造:

ConnectionConfig.custom().setCharset(Charsets.toCharset(defaultEncoding)).build();

SocketConfig.custom().setSoTimeout(100000).build();

基本情况就是这样,接下来谈下怎样使用新的HttpClient来訪问自签名https接口。

參阅CSDN博主noodies代码,发现实现訪问自签名https的要点就是建立一个自己定义的SSLContext对象。该对象要有能够存储信任密钥的容器。还要有推断当前连接是否受信任的策略,以及在SSL连接工厂中取消对全部主机名的验证。他的代码将会在本文最后贴出来,下面代码均针对新HttpClient。

首先建立一个信任不论什么密钥的策略。代码非常easy,不去考虑证书链和授权类型,均觉得是受信任的:

class AnyTrustStrategy implements TrustStrategy{

	@Override
	public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
		return true;
	}

}

HttpClient既能处理常规http协议,又能支持https,根源在于在连接管理器中注冊了不同的连接创建工厂。当訪问url的schema为http时,调用明文连接套节工厂来建立连接。当訪问url的schema为https时,调用SSL连接套接字工厂来建立连接。对于http的连接我们不做修改。仅仅针对使用SSL的https连接来进行自己定义:

RegistryBuilder<ConnectionSocketFactory> registryBuilder = RegistryBuilder.<ConnectionSocketFactory>create();
ConnectionSocketFactory plainSF = new PlainConnectionSocketFactory();
registryBuilder.register("http", plainSF);
//指定信任密钥存储对象和连接套接字工厂
try {
	KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
	SSLContext sslContext = SSLContexts.custom().useTLS().loadTrustMaterial(trustStore, new AnyTrustStrategy()).build();
	LayeredConnectionSocketFactory sslSF = new SSLConnectionSocketFactory(sslContext, SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
	registryBuilder.register("https", sslSF);
} catch (KeyStoreException e) {
	throw new RuntimeException(e);
} catch (KeyManagementException e) {
	throw new RuntimeException(e);
} catch (NoSuchAlgorithmException e) {
	throw new RuntimeException(e);
}
Registry<ConnectionSocketFactory> registry = registryBuilder.build();

在上述代码中能够看到。首先建立了一个密钥存储容器,随后让SSLContext开启TLS,并将密钥存储容器和信任不论什么主机的策略载入到该上下文中。构造SSL连接工厂时,将自己定义的上下文和同意不论什么主机名通过校验的指令一并传入。最后将这样一个自己定义的SSL连接工厂注冊到https协议上。

前期准备已经完毕,接下来我们要获得HttpClient对象:

//设置连接管理器
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(registry);
connManager.setDefaultConnectionConfig(connConfig);
connManager.setDefaultSocketConfig(socketConfig);
//构建客户端
HttpClient client= HttpClientBuilder.create().setConnectionManager(connManager).build();

为了让我们的HttpClient具有多线程处理的能力,连接管理器选用了PoolingHttpClientConnectionManager,将协议注冊信息传入连接管理器,最后再次利用构造器的模式创建出我们须要的HttpClient。随后的GET/POST请求发起方法http和https之间没有差异。

为了验证我们的代码是否成功,能够做下JUnit单元測试:

@Test
public void doTest() throws ClientProtocolException, URISyntaxException, IOException{
	HttpUtil util = HttpUtil.getInstance();
	InputStream in = util.doGet("https://kyfw.12306.cn/otn/leftTicket/init");
	String retVal = HttpUtil.readStream(in, HttpUtil.defaultEncoding);
	System.out.println(retVal);
}

运行后能够在控制台看到12306余票查询界面的html代码

为了方便大家使用,本人将封装好的代码上传到了CSDN资源共享中,欢迎下载。

下载地址:http://download.csdn.net/detail/chaijunkun/8046331

最后感谢CSDN博主noodies的代码提供了思路:http://blog.csdn.net/noodies/article/details/17240805

本文中的部分代码參阅了HttpClient 4.3.5官方文档的2.7节关于Connection socket factories的内容

时间: 2024-10-05 19:34:51

基于HttpClient 4.3的可訪问自签名HTTPS网站的新版工具类的相关文章

基于HttpClient 4.3的可访问自签名HTTPS站点的新版工具类

本文出处:http://blog.csdn.net/chaijunkun/article/details/40145685,转载请注明.由于本人不定期会整理相关博文,会对相应内容作出完善.因此强烈建议在原始出处查看此文. HttpClient在当今Java应用中的位置越来越重要.从该项目的变迁过程我们不难发现,其已经从apache-commons众多的子项目中剥离,一跃成为如今的顶级项目,可见它的分量.然而随着项目的升级和架构的调整,很多以前常用的类和方法都已被打上了@Deprecated注解,

使用FREDATED引擎实现跨实例訪问

跨数据库server.跨实例訪问是比較常见的一种訪问方式,在Oracle中能够通过DB LINK的方式来实现. 对于MySQL而言,有一个FEDERATED存储引擎与之相相应.相同也是通过创建一个链接方式的形式来訪问远程server上的数据.本文简要描写叙述了FEDERATED存储引擎.以及演示了基于FEDERATED存储引擎跨实例訪问的演示样例. 1.FEDERATED存储引擎的描写叙述  FEDERATED存储引擎同意在不使用复制或集群技术的情况下实现远程訪问数据库  创建基于FEDERAT

NGINX之——配置HTTPS加密反向代理訪问–自签CA

转载请注明出处:http://blog.csdn.net/l1028386804/article/details/46695495 出于公司内部訪问考虑,採用的CA是本机Openssl自签名生成的,因此无法通过互联网工信Root CA验证,所以会出现该站点不受信任或安全证书无效的提示.直接跳过,直接訪问就可以! HTTPS的原理和訪问过程: server必要条件 一个server私钥 KEY文件 一张与server域名匹配的CA证书(公钥,依据私钥key生成) 訪问过程: 1,client浏览器

objective-c訪问控制符

objective-c中成员变量的四个訪问控制符: @private:仅仅有当前类的内部才干訪问 @public:全部人都可訪问 @protected:仅仅限当前类和它的子类可以訪问 @package:让那些受它控制的成员变量不仅能够在当前类中訪问.也可在同样映像的其它程序中訪问. 什么是"同一映像"? 就是编译后生成的同一框架或同一个运行文件. 即当前框架可以訪问,可是外部程序无法訪问. (假设是public的话.外部程序也可以訪问). @private @package @prot

Java 訪问权限控制:你真的了解 protected keyword吗?

摘要: 在一个类的内部,其成员(包含成员变量和成员方法)是否能被其它类所訪问,取决于该成员的修饰词:而一个类是否能被其它类所訪问,取决于该类的修饰词.Java的类成员訪问权限修饰词有四类:private,无(默认情况下.包訪问权限),protected 和 public,而当中仅仅有包訪问权限和public才干修饰一个类(内部类除外).特别地,非常多的介绍Java的书籍对protected介绍的比較笼统,经常会对大家造成误解. 因此,本文重点揭示了 protected 关键字的内涵和使用方法,并

C++类訪问控制及继承

一.C++类的訪问控制有三类:public,protected和private. 类訪问控制符 类成员可被哪些对象訪问 public 1.类的成员函数.2.类对象.3.友元.4.子类成员函数 protected 1.类的成员函数.2.友元.3.子类成员函数 private 1.类的成员函数.2.友元 二.C++类的继承 继承方式也有三种:public,protected和private. 继承之后,基类成员的可訪问性会发生变化,例如以下表: public继承 基类 public protecte

JAVA基础之訪问控制权限(封装)

包:库单元 1.当编写一个Java源码文件时.此文件通常被称为编译单元(有时也被称为转译单元). 2.每一个编译单元都必须有一个后缀名.java,而在编译单元内则能够有一个public类,该类名称必须和文件的名称同样. 3.每一个编译单元仅仅能有一个public类,否则编译器就不会接受. 4.假设在该编译单元之中还有额外的类的话,那么在包之外的世界是无法看见这些类的,由于它们不是public类. 代码组织 xx.java编译生成xx.class package语句必须是文件除凝视以外的第一句程序

3.5 訪问者模式(5.11)

訪问者模式的学习.能够从以下方面入手. 假设一门编程语言支持双分派(多分派).那么訪问者模式就没有太大的存在价值.其实,看完Java模拟 双分派Double Dispatch,你应该自己做最后的题目:改动上述代码.使得消息a.foo(b),当中a声明为X类型变量.b声明为Z类型变量.题目做完了,訪问者模式你就自己搞出来了. 所以,--要在訪问者模式基础上玩花样时,我们再继续. 訪问者模式的意图,方便于给一个类增添新的接口. 为什么GoF要提到"某种对象结构"和元素呢?好多网上的样例,讲

J2SE基础:3.对象的创建与使用类的命名空间和訪问权限

1:package包. 包(package)是类的容器.用来保存划分类名空间. 逻辑意义对类进行划分. 解决同名的类的冲突问题. 2:package的命名规范: A:package必须写在源文件的第一行. B:package名一律使用小写. C:(建议)package使用公司的域名倒过来. www.demo.com com.demo.项目名称.模块名称 3:包在逻辑上是以命名空间划分的. 在物理上是以文件系统路径划分的. com.demo.one 将类编译好后,要将编译好的类放到com/demo