说明:本文主要是在平时接口对接开发中遇到的为保证传输安全的情况特要求使用https进行交互的情况下,使用httpClient4.5版本对HTTPS的双向验证的  功能的实现
    首先,老生常谈,文章将按照哲学三部曲来解答什么是https,为什么要使用https,httpClient怎么实现https及双向验证。
    问题1:什么是https?
    https:安全的超文本传输协议;其实质是
    加密+认证+完整性保护的HTTP,
    也就是说是http的安全版本,https由http进行通信,但利用SSL/TLS协议来加密数据包,并提供对网站服务器的身份认证,保护交换数据的隐私与完整性 。
    问题2:为什么要使用https协议?
    没有任何一个东西是完美的,总所周知,https出现以前,哪怕是直到现在我们见到更多的还是http协议,那么为什么我们要使用https协议呢?一般来说https是安全的http协议,我们更多的用于支付场景中,https协议主要针对解决http协议以下不足:
    1.http使用明文(不加密)通信,内容可能会被窃听
    2.不对通信方身份进行认证,可能遭遇伪装攻击
    3.无法证明报文的完整性(即准确性),报文可能已被篡改
    同样的虽然https解决了HTTP存在的一些问题,但是https的本质是将http的通信接口加入了SSL/TLS协议进行加密处理,加密通信会消耗更多的cup以及内存资源。同样在三次握手事,相对效率会变低,除此之外,要进行https通信,证书是必不可少的。而是用证书必须向认证机构(CA)购买。
    问题3:httpClient怎么实现https及双向验证?
    对接的服务端发送过来的证书是pfx格式的证书,正常来讲pfx格式证书是包含了公钥/私钥/证书信息等的PKCS12证书,然而直接使用pfx证书作为keyStore却一直报错no trusted certificate error,因此在网上查询了一天,终于把这个问题解决了,解决方案如下:
    先将.pfx文件转为.cer文件,再将.cer文件使用keytool工具导入$JAVA_HOME/jre/lib/security/cacerts中,cacerts证书库的默认密码为changeit;
    1.pfx文件转为cer文件的方法:
        1.使用IE浏览器
    2.将.cer文件使用keytool工具导入cacerts证书库
        1.keytool -import -alias testCer -keystore cacerts -file C:\Users\admin\Desktop\bcTest.cer
    3.java代码中的文件配置
        初始化keyStore:为pfx证书路径与密码,策略为PKCS12
        初始化trustStore:为cacerts证书库地址,策略为JKS,cacerts证书库默认密码为changeit
    Java代码实现:

     package com.test.sendhttps;

     import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
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.util.Iterator;
import java.util.Map;
import java.util.Set;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;
import com.test.util.JsonUtils;
import com.test.util.PropertiesUtil; public class SendHttps {
private static Logger log = Logger.getLogger(SendHttps.class);
static String keyStorePath ;
static String keyStorePassword ;
static String keyStoreType ;
static String trustStorePath ;
static String trustStorePassword ;
static String trustStoreType;
static{
PropertiesUtil proUtil; //配置文件读取
try {
proUtil = new PropertiesUtil();
keyStorePath = proUtil.readValue("sslKeyStorePath");
keyStorePassword = proUtil.readValue("sslKeyStorePassword");
keyStoreType = proUtil.readValue("sslKeyStoreType");
trustStorePath = proUtil.readValue("sslTrustStore");
trustStorePassword = proUtil.readValue("sslTrustStorePassword");
trustStoreType = proUtil.readValue("sslTrustStoreType");
} catch (IOException e) {
// TODO Auto-generated catch block
log.error("配置文件读取异常");
e.printStackTrace();
}
} public static String sendToHttps(String reqMsg, String url, Map<String, String> headMap) {
log.info("keyFactory");
//初始化KeyManager
KeyManagerFactory keyFactory = null;
try {
keyFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
KeyStore keystore = KeyStore.getInstance(keyStoreType);
keystore.load(new FileInputStream(new File(keyStorePath)), null);
keyFactory.init(keystore, keyStorePassword.toCharArray()); } catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (KeyStoreException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (CertificateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (UnrecoverableKeyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
KeyManager[] keyManagers = keyFactory.getKeyManagers();
//初始化Trust Manager
log.info("keyFactory ="+keyFactory);
TrustManagerFactory trustFactory = null; try {
trustFactory = TrustManagerFactory.getInstance("SunX509");
} catch (NoSuchAlgorithmException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} KeyStore tsstore;
try {
tsstore = KeyStore.getInstance(trustStoreType);
tsstore.load(new FileInputStream(new File(trustStorePath)), trustStorePassword.toCharArray());
trustFactory.init(tsstore);
log.info("tsstore ="+tsstore+" || trustFactory = "+trustFactory);
} catch (KeyStoreException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (CertificateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} TrustManager[] trustManagers = trustFactory.getTrustManagers();
log.info("trustManagers ="+trustManagers);
//注册HtpClient
SSLContext sslContext = null;
try {
sslContext = SSLContext.getInstance("TLS");
sslContext.init(keyManagers, trustManagers, null);
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (KeyManagementException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
log.info("sslContext ="+sslContext); //设置规则限制
SSLConnectionSocketFactory ssf = new SSLConnectionSocketFactory(sslContext,
new String[]{"TLSv1","TLSv1.1","TLSv1.2"},null,
new HttpsHostnameVerifier());
//注册
Registry<ConnectionSocketFactory> socketFactoryRegistry = null;
socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory> create()
.register("http", PlainConnectionSocketFactory.INSTANCE)
.register("https", ssf).build();
//池化管理
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
//创建httpClient
CloseableHttpClient httpClient;
httpClient = HttpClients.custom().setConnectionManager(connManager).build(); //设置httpPost
HttpPost httpPost = new HttpPost(url);
if ((!headMap.isEmpty()) && (headMap.size() > 0)) {
Set<String> keys = headMap.keySet();
for (Iterator<String> i = keys.iterator(); i.hasNext(); ) {
String key = ObjectUtils.toString(i.next());
if("host".equals(key)){
continue;
}else{
log.info("key="+key+",value="+(String)headMap.get(key));
httpPost.addHeader(key, (String)headMap.get(key));
}
}
}
StringEntity reqEntity = new StringEntity(reqMsg, "UTF-8"); Header[] types = httpPost.getHeaders("Content-Type");
if ((types == null) || (types.length < 1)) {
httpPost.addHeader("Content-Type", "application/json;charset=utf-8");
} httpPost.setEntity(reqEntity);
CloseableHttpResponse response;
try {
response = httpClient.execute(httpPost);
} catch (Exception e) {
e.printStackTrace();
return null;
}
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode != HttpStatus.SC_OK) {
httpPost.abort();
return JsonUtils.setError("Fail to connect . response code = " + statusCode + ". error.");
} HttpEntity entity = response.getEntity();
String result = null;
try {
if (entity != null) {
result = EntityUtils.toString(entity, "utf-8");
}
EntityUtils.consume(entity);
response.close();
} catch (Exception e) {
log.error("Change charset to utf-8 error.");
return JsonUtils.setError("Change charset to utf-8 error.");
}
return result;
}
}

https设置主机名校验

         package com.test.sendhttps;

         import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLSession; public class HttpsHostnameVerifier implements HostnameVerifier { /**
* 验证对方主机名称 ,防止服务器证书上的Hostname和实际的URL不匹配
* 防止链接被重定向到其他的不安全的地址
*/
@Override
public boolean verify(String hostname, SSLSession session) {
System.out.println("hostname = [" + hostname + "],session = [" + session.getPeerHost() + "]");
if (hostname.equals("地址") || session.equals("地址"))
return true;
else
return false;
}
}

配置信息 config.propertities:

sslKeyStorePath=pfx文件路径
sslKeyStorePassword=pfx文件密码
sslKeyStoreType=PKCS12
#jdk中的cacerts库地址
sslTrustStore=C:/Program Files/Java/jre7/lib/security/cacerts
#cacerts库密码
sslTrustStorePassword=changeit
#cacerts库默认类型
sslTrustStoreType=JKS

后续更换证书操作
    查看cacerts证书库中的所有证书
    keytool -list -keystore cacerts
    删除证书库中别名为testCer的证书
    keytool -delete -alias testCer -keystore cacerts
    再次导入证书
    keytool -import -alias testCer -keystore cacerts -file C:\Users\admin\Desktop\testCer.cer

以上即是所有内容,如有不正确之处,欢迎各位大神批评,斧正,谢谢

使用HttpClient4.5实现HTTPS的双向认证的更多相关文章

  1. HTTPS 中双向认证SSL 协议的具体过程

    HTTPS 中双向认证SSL 协议的具体过程: 这里总结为详细的步骤: ① 浏览器发送一个连接请求给安全服务器.② 服务器将自己的证书,以及同证书相关的信息发送给客户浏览器.③ 客户浏览器检查服务器送 ...

  2. https 单向双向认证说明_数字证书, 数字签名, SSL(TLS) , SASL_转

    转自:https 单向双向认证说明_数字证书, 数字签名, SSL(TLS) , SASL 因为项目中要用到TLS + SASL 来做安全认证层. 所以看了一些网上的资料, 这里做一个总结. 1. 首 ...

  3. .net core下用HttpClient和asp.net core实现https的双向认证

    关于https双向认证的知识可先行google,这时矸接代码. 为了双向认证,我们首先得准备两个crt证书,一个是client.crt,一个是server.crt,有时为了验证是否同一个根证书的验证, ...

  4. 转: https 单向双向认证说明_数字证书, 数字签名, SSL(TLS) , SASL

    转自: http://www.cnblogs.com/mailingfeng/archive/2012/07/18/2597392.html 因为项目中要用到TLS + SASL 来做安全认证层. 所 ...

  5. C#中实现https的双向认证

    1.  把浏览器中的证书导出为cer文件. 2.   代码如下: using System; using System.Net; using System.IO; using System.Secur ...

  6. HTTPS 双向认证构建移动设备安全体系

    HTTPS 双向认证构建移动设备安全体系 对于一些高安全性要求的企业内项目,我们有时希望能够对客户端进行验证.这个时候我们可以使用Https的双向认证机制来实现这个功能. 单向认证:保证server是 ...

  7. Tomcat服务器配置https双向认证(使用keytool生成证书)

    一,HTTPS原理   1,HTTP.HTTPS.SSL.TLS介绍与相互关系 (1)HTTP:平时浏览网页时候使用的一种协议.HTTP协议传输的数据都是未加密的(明文),因此使用HTTP协议传输隐私 ...

  8. iOS + Nodejs SSL/Https双向认证

    移动互联网的大力发展,安全越来越重要. 什么是双向认证呢?双向认证就是client要验证server的合法性,同一时候server也要验证client的合法性. 这样两方都相互验证,提高安全性. 关于 ...

  9. phantomjs 双向认证,访问nginx,https

    应用背景: phantomjs的一个爬虫,访问https站点,单向认证(只认证服务器身份)的都可以,双向认证(服务器和客户端都需要认证)必须上传本地证书: 开始用一个包含公钥私钥的PEM证书访问,怎么 ...

随机推荐

  1. 【BZOJ2440】完全平方数(二分答案,莫比乌斯反演)

    [BZOJ2440]完全平方数(二分答案,莫比乌斯反演) 题面 BZOJ 题解 很显然,二分一个答案 考虑如何求小于等于这个数的非完全平方数倍数的个数 这个明显可以直接,莫比乌斯反演一下 然后这题就很 ...

  2. webpack3中使用postcss-loader和autoprefixer给css3样式添加浏览器兼容

    1.在webpack中需要处理css必须先安装如下两个loader npm install --save-dev css-loader style-loader 2.要处理sass和添加浏览器前缀需要 ...

  3. JAVA通过COM接口操作PPT

    一. 背景说明 在Eclipse环境下,开发JAVA代码操作PPT,支持对PPT模板的修改.包括修改文本标签.图表.表格.满足大多数软件生成PPT报告的要求,即先收工创建好模板,在程序中修改模板数据. ...

  4. spring中aop的注解实现方式简单实例

    上篇中我们讲到spring的xml实现,这里我们讲讲使用注解如何实现aop呢.前面已经讲过aop的简单理解了,这里就不在赘述了. 注解方式实现aop我们主要分为如下几个步骤(自己整理的,有更好的方法的 ...

  5. error:com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException

    问题:同样的代码,只能插入一组值,第二组值插入不了 解决:开始我将app_id作为主键,但很明显,同一个app_id会有不同的index,而同一个index也可能对应不同的app_id,因此只能添加一 ...

  6. 题目1032:ZOJ

    题目描述: 读入一个字符串,字符串中包含ZOJ三个字符,个数不一定相等,按ZOJ的顺序输出,当某个字符用完时,剩下的仍然按照ZOJ的顺序输出. 输入: 题目包含多组用例,每组用例占一行,包含ZOJ三个 ...

  7. Redis分布式锁的正确实现方式

    前言 分布式锁一般有三种实现方式:1. 数据库乐观锁:2. 基于Redis的分布式锁:3. 基于ZooKeeper的分布式锁.本篇博客将介绍第二种方式,基于Redis实现分布式锁.虽然网上已经有各种介 ...

  8. Excel中choose函数的使用方法

    你还在为Excel中choose函数的使用方法而苦恼吗,今天小编教你Excel中choose函数的使用方法,让你告别Excel中choose函数的使用方法的烦恼. 经验主要从四方面对Excel函数进行 ...

  9. Asp.Net MVC 文件管理Demo(文件展示,上传,下载,压缩,文件重命名等)

    之前 ,有想做一个文件管理页面. 参考了 许多资料,终于完成了一个基于Asp.net MVC 的文件管理Demo.界面如下.   一,实现功能及相关技术 文件管理Demo基于Asp.NET MVC , ...

  10. SignalR Self Host+MVC等多端消息推送服务(2)

    一.概述 上次的文章中我们简单的实现了SignalR自托管的服务端,今天我们来实现控制台程序调用SignalR服务端来实现推送信息,由于之前我们是打算做审批消息推送,所以我们的demo方向是做指定人发 ...