HttpClient实现https调用
在HttpClient 4.x版本中引入了大量的构造器设计模式
https请求建立详解
首先建立一个信任任何密钥的策略。代码很简单,不去考虑证书链和授权类型,均认为是受信任的:
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 registryBuilder = RegistryBuilder.create();
ConnectionSocketFactory plainSF =newPlainConnectionSocketFactory();
registryBuilder.register("http", plainSF);
//指定信任密钥存储对象和连接套接字工厂
try{
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
SSLContext sslContext = SSLContexts.custom().useTLS().loadTrustMaterial(trustStore,newAnyTrustStrategy()).build();
LayeredConnectionSocketFactory sslSF =newSSLConnectionSocketFactory(sslContext, SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
registryBuilder.register("https", sslSF);
}catch(KeyStoreException e) {
thrownewRuntimeException(e);
}catch(KeyManagementException e) {
thrownewRuntimeException(e);
}catch(NoSuchAlgorithmException e) {
thrownewRuntimeException(e);
}
Registry registry = registryBuilder.build();
在上述代码中可以看到,首先建立了一个密钥存储容器,随后让SSLContext开启TLS,并将密钥存储容器和信任任何主机的策略加载到该上下文中。构造SSL连接工厂时,将自定义的上下文和允许任何主机名通过校验的指令一并传入。最后将这样一个自定义的SSL连接工厂注册到https协议上。
//设置连接管理器
PoolingHttpClientConnectionManager connManager =newPoolingHttpClientConnectionManager(registry);
connManager.setDefaultConnectionConfig(connConfig);
connManager.setDefaultSocketConfig(socketConfig);
//构建客户端
HttpClient client= HttpClientBuilder.create().setConnectionManager(connManager).build();
为了让我们的HttpClient具有多线程处理的能力,连接管理器选用了PoolingHttpClientConnectionManager,将协议注册信息传入连接管理器,最后再次利用构造器的模式创建出我们需要的HttpClient。随后的GET/POST请求发起方法http和https之间没有差异。
为了验证我们的代码是否成功,可以做下JUnit单元测试:
@Test
publicvoiddoTest()throwsClientProtocolException, 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代码
- 有朋友反馈说提供的工具类中没有直接POST JSON对象的方法,下面我提供一下基础方法,供参考(此代码未包含在下文的共享资源中,请自行补充进去)
/**
* 基本Post请求
* @param url 请求url
* @param queryParams 请求头的查询参数
* @param json 直接放入post请求体中的文本(请使用JSON)
* @return
* @throws URISyntaxException
* @throws UnsupportedEncodingException
*/
publicHttpResponse doPostBasic(String url, Map queryParams, String json)throwsURISyntaxException, ClientProtocolException, IOException{
HttpPost pm =newHttpPost();
URIBuilder builder =newURIBuilder(url);
//填入查询参数
if(MapUtils.isNotEmpty(queryParams)){
builder.setParameters(HttpUtil.paramsConverter(queryParams));
}
pm.setURI(builder.build());
//填入post json数据
if(StringUtils.isNotBlank(json)){
//下面的ContentType完整类名为:org.apache.http.entity.ContentType
pm.setEntity(new StringEntity(json, ContentType.APPLICATION_JSON));
}
return client.execute(pm);
}
- 下面再列举一个传入指定秘钥的https访问方法
public void initSSLConfigForTwoWay() throws Exception {
HttpClientBuilder b = HttpClientBuilder.create();
// 1 Import your own certificate
// String demo_base_Path = System.getProperty("user.dir");
// String demo_base_Path = getClass().getClassLoader().getResource("").getPath();
// String selfcertpath = demo_base_Path + Constant.SELFCERTPATH;
// String trustcapath = demo_base_Path + Constant.TRUSTCAPATH;
// String selfcertpath = demo_base_Path + Constant.SELFCERTPATH;
// String trustcapath = demo_base_Path + Constant.TRUSTCAPATH;
KeyStore selfCert = KeyStore.getInstance("pkcs12");
selfCert.load(getClass().getClassLoader().getResourceAsStream(NbConstant.CERT_FLODER + File.separatorChar + NbConstant.SELFCERTPATH),
NbConstant.SELFCERTPWD.toCharArray());
KeyManagerFactory kmf = KeyManagerFactory.getInstance("sunx509");
kmf.init(selfCert, NbConstant.SELFCERTPWD.toCharArray());
// 2 Import the CA certificate of the server,
KeyStore caCert = KeyStore.getInstance("jks");
caCert.load(getClass().getClassLoader().getResourceAsStream(NbConstant.CERT_FLODER + File.separatorChar + NbConstant.TRUSTCAPATH), NbConstant.TRUSTCAPWD.toCharArray());
TrustManagerFactory tmf = TrustManagerFactory.getInstance("sunx509");
tmf.init(caCert);
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
// 3 Set the domain name to not verify
// (Non-commercial IoT platform, no use domain name access generally.)
SSLSocketFactory ssf = new SSLSocketFactory(sc, new String[]{"TLSv1.2", "TLSv1.1", "TLSv1"}, null,
SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
// If the platform has already applied for a domain name which matches
// the domain name in the certificate information, the certificate
// domain name check can be enabled (open by default)
// SSLSocketFactory ssf = new SSLSocketFactory(sc);
// ClientConnectionManager ccm = this.getConnectionManager();
// SchemeRegistry sr = ccm.getSchemeRegistry();
// sr.register(new Scheme("https", 8743, ssf));
Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.getSocketFactory())
.register("https", ssf)
.build();
// -- allows multi-threaded use
PoolingHttpClientConnectionManager connMgr = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
connMgr.setMaxTotal(200);
connMgr.setDefaultMaxPerRoute(100);
b.setConnectionManager(connMgr);
// finally, build the HttpClient;
// -- done!
// httpClient = new DefaultHttpClient(ccm);
httpClient = b.build();
}
HttpClient实现https调用的更多相关文章
- 用HttpClient发送HTTPS请求报SSLException: Certificate for <域名> doesn't match any of the subject alternative names问题的解决
最近用server酱-PushBear做消息自动推送,用apache HttpClient做https的get请求,但是代码上到服务器端就报javax.net.ssl.SSLException: Ce ...
- Httpclient 支持https(转)
参考:https://jingyan.baidu.com/article/154b46317353d228ca8f4112.html 参考:https://www.jianshu.com/p/a444 ...
- HttpClient远程接口调用-实名认证
1.HttpClient远程接口调用 1)用户注册 注册按钮button提交表单时,要return false form表单 <!-- action="http://localhost ...
- 使用HttpClient发送HTTPS请求以及配置Tomcat支持SSL
这里使用的是HttpComponents-Client-4.1.2 package com.jadyer.util; import java.io.File; import java.io.FileI ...
- android httpClient 支持HTTPS的2种处理方式
摘自: http://www.kankanews.com/ICkengine/archives/9634.shtml 项目中Android https或http请求地址重定向为HTTPS的地址,相信很 ...
- c# 中HttpClient访问Https网站
c# 中HttpClient访问Https网站,加入如下代码: handler = new HttpClientHandler() ;handler.AllowAutoRedirect = true; ...
- httpclient妙用一 httpclient作为客户端调用soap webservice(转)
前面有一篇使用HttpClient调用带参数的post接口方法,这里找到一篇使用HttpClient调用Soap协议接口的方式. 原文地址:httpclient妙用一 httpclient作为客户端调 ...
- 前端https调用后端http
昨晚发生了一个,很........的事 我前端的域名 和后端的域名 都没有做认证,前端的访问的80 调用的后端80 然后我给前端的域名做了认证ssl,但是调用后端的时候报错 原因是 https 调 ...
- https 调用验证失败 peer not authenticated
https 调用验证失败 peer not authenticated 报错日志: Caused by: javax.net.ssl.SSLPeerUnverifiedException: peer ...
- 微信的API都是通过https调用实现的,分为post方法调用和get方法调用。不需要上传数据的采用get方法(使用IntraWeb开发)
首先需要明确的是,微信的API都是通过https调用实现的,分为post方法调用和get方法调用.不需要上传数据的采用get方法(例如获取AccessToken),而需要向微信服务器提交数据的采用po ...
随机推荐
- js 闭包详解一
闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现. 下面就是我的学习笔记,对于Javascript初学者应该是很有用的. 一.变量的作用域 要理解 ...
- 消息队列RabbitMQ教程
RabbitMQ教程 翻译自RabbitMQ Tutorials. 0. 准备 前期准备 1. Hello World 最简入门教程 2. 工作队列 竞争消费者模式 3. 发布/订阅 同时发送消息给多 ...
- vim 从嫌弃到依赖(5)——普通模式的一些操作
通过前面几章内容的铺垫,基本已经介绍完了普通模式的大部分内容,按照进度下面会依次介绍插入模式.命令模式.选择模式的一些操作.根据不同模式提供功能的多少和使用频率,篇幅会有长有短.本来这篇文章应该介绍插 ...
- C++ CryptoPP使用AES加解密
Crypto++ (CryptoPP) 是一个用于密码学和加密的 C++ 库.它是一个开源项目,提供了大量的密码学算法和功能,包括对称加密.非对称加密.哈希函数.消息认证码 (MAC).数字签名等.C ...
- 4.6 Windows驱动开发:内核遍历进程VAD结构体
在上一篇文章<内核中实现Dump进程转储>中我们实现了ARK工具的转存功能,本篇文章继续以内存为出发点介绍VAD结构,该结构的全程是Virtual Address Descriptor即虚 ...
- STM32CubeMX教程28 SDIO - 使用FatFs文件系统读写SD卡
1.准备材料 正点原子stm32f407探索者开发板V2.4 STM32CubeMX软件(Version 6.10.0) keil µVision5 IDE(MDK-Arm) ST-LINK/V2驱动 ...
- LeetCode刷题日记2020/8/24
题目描述 给定一个非空的字符串,判断它是否可以由它的一个子串重复多次构成.给定的字符串只含有小写英文字母,并且长度不超过10000. 示例 1: 输入: "abab" 输出: Tr ...
- Windows7 SP1 安装.NET Framework4失败
系统版本是Windows7旗舰版,已经安装了SP1补丁,但还是无法安装.NET Framework4或者4.5,提示安装失败. 这时可以安装.NET Framework4.8的开发包,我这里安装开发包 ...
- SPFA -----队列优化的Bellman-Ford
SPFA ------队列优化的Bellman-Ford 由Bellman-Ford算法实现带有负权边的单源最短路,时间复杂度是O(VE),也就是边数乘顶点数.但是根据Bellman-Ford的状态转 ...
- 12c/19c新特性官方文档快速参考
工作中会经常遇到被询问Oracle某一个新特性,是在哪个版本开始引入,通常都去查官方文档New Features部分章节,下面列出从12.1.0.1 到 19c的对应在线官方文档的链接,方便快速检索: ...