java实现HTTPS单向认证TLS指定加密套件(文章很详细,好文章!)
1、HTTPS介绍
由于HTTP是明文传输,会造成安全隐患,所以在一些特定场景中,必须使用HTTPS协议,简单来说HTTPS=HTTP+SSL/TLS。服务端和客户端的信息传输都是通过TLS进行加密。这样就能在一定程度上避免敏感信息被截取。
在通信过程中,请求方称为客户端,响应方称为服务端。HTTPS请求流程如图:
1、客户端向服务端发送加密版本、加密算法种类、随机数信息等。
2、服务端返回客户端发送的信息并带上服务端证书(公钥证书)。
3、客户端效验服务端证书的合法性。
4、验证不通过终止通信,验证通过继续通信,客户端将自己所支持的所有加密算法全部发送给服务端供服务端进行选择。
5、服务端在客户端发送的加密算法中选择加密程度最高的机密方式。
6、服务端将选择的加密算法通过明文返回给客户端。
7、客户端收到服务端返回的加密方式后,使用该加密方式生成随机码(用作后续通信过程中加密的秘钥),使用服务端返回的公钥加密后发送至服务端。
8、服务端收到信息后,使用自己的私钥进行解密,获取加密秘钥。
在之后的通信中,客户端和服务端都将采用该秘钥进行加密。
2、自签证书的生成
生成证书和转换证书格式需要密码,秘密建议全部设置一致的。
2.1 生成根证书
# 生成root私钥
openssl genrsa -out root.key 1024
# 根据私钥创建根证书请求文件,需要输入一些证书的元信息:邮箱、域名、密码等
openssl req -new -out root.csr -key root.key
# 结合私钥和请求文件,创建根证书,有效期10年
openssl x509 -req -in root.csr -out root.crt -signkey root.key -CAcreateserial -days 3650
2.2 生成服务端证书
# 创建服务端私钥
openssl genrsa -out server.key 1024
# 根据私钥生成请求文件需要证书元信息:邮箱、域名、密码等
openssl req -new -out server.csr -key server.key
# 结合私钥和请求文件创建服务端证书,有效期10年
openssl x509 -req -in server.csr -out server.crt -signkey server.key -CA root.crt -CAkey root.key -CAcreateserial -days 3650
单向认证不需要生成客户端证书,所以做单向认证的证书到此就完成了。但是为了之后的测试方便(java中作为服务端使用.p12/.jks类型比较方便,作为客户端使用.p12/.jks比较方便),将生成的证书进一步转换。
2.3 证书类型转换
# 根证书crt转p12需要密码
openssl pkcs12 -export -in root.crt -inkey root.key -out root.p12
# 服务端证书crt转p12需要密码
openssl pkcs12 -export -in server.crt -inkey server.key -out server.p12
# p12转jks需要密码(实际项目中可以不用,仅做测试)
keytool -importkeystore -srckeystore root.p12 -srcstoretype PKCS12 -deststoretype JKS -destkeystore root.jks
生成的全部文件如下:
使用java实现:服务端需要server.p12文件,客户端需要root.p12文件。可以有其他不同的实现方式,需要不同类型的文件可以通过openssl或者keytool进行证书格式转化。(jks格式只是用来测试实际项目中可以不生成)。
3、自签证书的使用
3.1 服务端配置
1、证书放到resources目录下(其他目录也可以,配置文件中写好对应路径就行)
2、在application中添加配置
# 新增http端口
server.port=8075
# 证书路径resource下
server.ssl.key-store=classpath:server.p12
# 密码
server.ssl.key-store-password=hcm@123++
# 服务端限定加密算法
server.ssl.ciphers=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
# 服务端限定TLS版本
server.ssl.protocol=TLSv1.2
根据实际项目中,客户端和服务端都限定使用这两种算法。
3、配置之后启动项目,之前的端口就是https端口了,这样就不能使用http访问了,需要使用以下代码同时支持http。
//配置http
@Bean
public ServletWebServerFactory servletContainer() {
TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
tomcat.addAdditionalTomcatConnectors(createStandardConnector());
return tomcat;
}
private Connector createStandardConnector() {
Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
connector.setPort(“需要使用的http端口”);
return connector;
}
启动项目出现一个http端口一个https端口就是端口开启成功了
可以写个测试方法测试一下
可以看出http和https均可以访问,至此服务端配置完成并且测试通过。
3.2 客户端配置
客户端配置有两种方案,其一是把根证书导入到jdk中,其二就是本次使用的代码实现。
由于不太了解导入到jdk是不是有隐患,所有对第一种方案并没有深入研究,简单的导入命令如下
# 添加cacerts:
keytool -import -v -trustcacerts -alias 1 -file "C:\Users\zhouyinhang\Desktop\fsdownload\testca1\root.crt" -keystore "G:\Program Files\java\jdk1.8.0_181\jre\lib\security\cacerts"
# 查看cacerts中的证书列表:
keytool -list -keystore "C:\Program Files\Java\jre1.8.0_181\lib\security\cacerts" -storepass changeit
# 删除cacerts中指定名称的证书:
keytool -delete -alias 1 -keystore "G:\Program Files\java\jdk1.8.0_181\jre\lib\security\cacerts" -storepass changeit
其中-alias 1 “1”为别名可以通过命令keytool -list -v -keystore root.p12查看,需要注意的是导入jdk的证书格式不可以是p12或者jks格式,可以使用最先生成的crt格式。
下面主要介绍第二种通过代码实现客户端根证书的使用。
通过代码实现主要构造httpClient类
httpClient类作用就是通过记载根证书、密码、配置TLS版本、配置支持的加密套件、配置是否域名效验返回一个CloseableHttpClient连接对象,使用该对象可以直接请求https服务端接口,也可以对CloseableHttpClient对象封装成ReatTemplate。具体实现可以参考源码。
下面代码是核心代码,包括如何建立SSLContext连接,TrustManager如何创建。
其中初始化SSLContext是传入三个参数分别是keyManagers(授权的秘钥管理器,用来验证授权),trustManagers(被授权的证书管理器,用来验证服务端证书),secureRandom(随机数,可以填null,SSLContext内部有实现)。项目中cac组件作为客户端时,而且是单向认证所以只需要传第二个参数即可。
public static CloseableHttpClient initSSLConfig() throws Exception {
//证书类型
KeyStore keyStore = KeyStore.getInstance("PKCS12");
//加载根证书
keyStore.load(new FileInputStream(PATH),PASSWORD.toCharArray());
// 创建信任库管理工厂实例
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("SunX509");
// 初始化信任库
trustManagerFactory.init(keyStore);
TrustManager[] tm = trustManagerFactory.getTrustManagers();
// 建立TLS连接
SSLContext sc = SSLContext.getInstance("TLSv1.2");
// 初始化SSLContext
sc.init(null, tm, null);
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
sc,
// 指定TLS版本
new String[]{"TLSv1.2"},
// 指定算法
new String[]{"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384","TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384"},
// 取消域名验证
new HostnameVerifier(){
@Override
public boolean verify(String string, SSLSession ssls) {
return true;
}
}
);
CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
return httpClient;
}
使用同一套证书测试结果
测试不同证书时候,有两种选择,其一把其他根证书签发的服务端证书放到请求的服务器上。其二客户端使用其他的根证书。(根证书和服务器证书不匹配)
错误信息如图
由此可以看出客户端已经使用根证书效验服务端返回的证书了。
demo只是作为测试使用,具体使用要结合实际项目。例如cac组件中基线没有用restTemplate,如果使用restTemplate的话改动太大,只能使用client直接发起请求的方式。
4、正确使用HTTPS
虽然在通信中有必要使用HTTPS,但是不能全部通信都使用,原因主要有两点:
- HTTPS需要认证,所以相对于HTTP来说效率肯定是比较慢的。
- 要进行HTTPS通信,必须要有证书,这些证书一般都需要向认证机构购买。
转载自:https://www.cnblogs.com/unchain/p/14821123.html
java实现HTTPS单向认证TLS指定加密套件(文章很详细,好文章!)相关推荐
- JAVA实现https单向认证
//关于http 须要两个jar包 httpclient-4.0.jar httpcore-4.0.1.jar private static final HttpClient httpClient = ...
- 扯一扯HTTPS单向认证、双向认证、抓包原理、反抓包策略
HTTP(HyperText Transfer Protocol,超文本传输协议)被用于在Web浏览器和网站服务器之间传递信息,在TCP/IP中处于应用层.这里提一下TCP/IP的分层共分为四层:应用 ...
- HTTPS单向认证,双向认证
HTTP(HyperText Transfer Protocol,超文本传输协议)被用于在Web浏览器和网站服务器之间传递信息,在TCP/IP中处于应用层.这里提一下TCP/IP的分层共分为四层:应用 ...
- Tomcat SSL/HTTPS 单向认证
前言 jdk 1.8 tomcat 7 jks证书库 准备 1.已经生成名为localhost.jks的证书库,证书库的密码为localhost. 2.证书库中有别名为localhost的证书,证书的 ...
- https 单向认证和双向认证
转载自 https 单向认证和双向认证 一.Http HyperText Transfer Protocol,超文本传输协议,是互联网上使用最广泛的一种协议,所有WWW文件必须遵循的标准.HTTP ...
- openssl https 单向认证连接成功示例
openssl https 单向认证连接成功示例 研究这个玩意也有几天的时间了,刚学C 因为不熟悉编译折腾了不少时间,终于弄通了,发个随笔给研究openssl https的同学一点提示吧. 环境: = ...
- 实现tomcat的https单向认证及双向认证
前言 单向认证只需站点部署了ssl证书就行,任何用户都可以去访问(IP被限制除外等),只是服务端提供了身份认证 一般web应用都是采用单向认证的,原因很简单,用户数目广泛,且无需做在通讯层做用户身份验 ...
- CAS 使用 HTTPS 单向认证方式 服务端和客户端配置
注:以下配置为本人亲测,如有问题请留言:转载请注明:http://blog.csdn.net/wqmain/article/details/8562602 目录结构如下: l 名词解释 l 测试环 ...
- Https单向认证和双向认证介绍
一.Http HyperText Transfer Protocol,超文本传输协议,是互联网上使用最广泛的一种协议,所有WWW文件必须遵循的标准.HTTP协议传输的数据都是未加密的,也就是明文的,因 ...
最新文章
- sqlplus连接时出现错误:shared memory realm does not exist 解决
- 检测到目标服务器启用了trace方法_CVPR2019目标检测方法进展综述
- python-68:BS4获取多个标签的文本
- java.lang.ClassCastException: com.sun.proxy.$Proxy2 cannot be cast to...异常
- iOS内存管理知识点
- linux php 升级5.3,Linux php5.2.10升级到PHP5.3.29
- 安装系统提示选中的磁盘具有MBR分区表
- 树与森林的存储、遍历和树与森林的转换
- [BZOJ2707]走迷宫
- EasyUI Tree判断节点是否是叶
- Ajax.BeginForm无法调用 ajaxOptions的js函数
- 在 Laravel 应用中使用 pjax 进行页面加速
- 算法研发---对宏定义#define相关研究
- 突然想起今天的博客汇报没写
- 新手如何检查MacBook电池的运行状况
- LeetCode_Maximum Subarray | Maximum Product Subarray
- bat命令 延迟执行
- 【python】CNN算法
- shell 脚本中常用的列表
- 视频教程-C语言编程入门100题(实战编程)-C/C++