内容简介:不知不觉(0)Https专题(1)
1 简介
不知不觉 Https
相关的文章已经写了6篇了,本文将是这个专题的最后一篇,起码近期是最后一篇。前面6篇讲的全都是单向的 Https
验证,本文将重点介绍一下双向验证。有兴趣的同学可以了解一下之前的文章:
(0)Https专题
(2) HTTPS之密钥知识与密钥工具Keytool和Keystore-Explorer
(3) Springboot以Tomcat为容器实现http重定向到https的两种方式
(4) Springboot以Jetty为容器实现http重定向到https
(5) nginx开启ssl并把http重定向到https的两种方式
(6) Springboot-WebFlux实现http重定向到https
双向验证是比较难的,能掌握双向验证,单向验证就没什么问题了。
2 单向验证与双向验证
2.1 概念和作用
所谓 单向验证 ( One Way SSL ),就是只有一方验证另一方是否合法,通常是客户端验证服务端。比如我们打开 www.pkslow.com 这个网站,服务端不会验证客户端,只要你来我就欢迎。但客户端不一样,浏览器会验证这个网站是不是安全的,一般是通过 CA 颁发的 SSL证书 来验证。
而 双向验证 ( Two Way SSL )则不同。不仅客户端需要验证服务端,服务端同样戒备心很重,也需要验证客户端是否是合法。
大家是否会有疑问,这么麻烦的 双向验证 有什么用?我们平常用 单向验证 不就已经足够了吗? 单向验证 虽然安全,但不够安全,使用 双向验证 可以只让特定的客户端访问,安全性会高一点。
另一方面,如果服务端没有做账户权限控制,但又想只限制特定的客户端访问, 双向验证 就非常有用,我只验证我相信的客户端,其它一概拒绝!这样即使我的服务暴露在网上,也不怕别人访问。既保证了安全,又省去了做权限控制的麻烦。
2.2 验证合法性
验证合法性通常是通过 Trust Store 。要求要把对方的 cert 装在自己的 Trust Store 里。
这就衍生出了一个之前没有讲过的概念: Trust Store 。密钥文件可以存放私钥和公钥,具体一点来说是可以存放自己的私钥、自己的公钥和别人的公钥(也可以存放别人的私钥,但这不合理,私钥必须私有)。一般地我们把自己的(私钥和公钥)存放在 Key Store 里,而把别人的公钥存放在 Trust Store 里。
以 Java 程序为例,我们建立 SSLContext 时,需要生成 KeyManager 和 TrustManager ,对应的参数为 javax.net.ssl.keyStore 和 javax.net.ssl.trustStore 。而它们的作用正好体现了不同 Store 的作用:
-
TrustManager:决定对方来的 cert 是不是可信的;
-
KeyManager:决定自己发什么 cert 给对方。
如果我们不指定 TrustStore ,默认是 $JAVA_HOME/jre/lib/security/cacerts
文件。我们可以通过命令查看这个文件都有什么 certs :
keytool -list -keystore cacerts
2.3 单向验证的流程
单向验证的流程如下图所示:
建立连接的过程:
-
客户端向服务端发送SSL协议版本号、加密算法种类、随机数等信息;
-
服务端给客户端返回SSL协议版本号、加密算法种类、随机数等信息,同时也返回 服务器端的证书 ,即公钥证书;
-
客户端使用服务端返回的信息 验证服务器端的合法性 ,包括:
(1)证书是否过期
(2)颁发服务器证书的CA是否可靠
(3)返回的公钥是否能正确解开返回证书中的数字签名
(4)服务器证书上的域名是否和服务器的实际域名相匹配
验证通过后,将继续进行通信,否则,终止通信;
-
客户端向服务端发送自己所能支持的 对称加密方案 ,供服务器端进行选择;
-
服务器端在客户端提供的加密方案中选择加密程度最高的 加密方式 ;
-
服务器将选择好的 加密方案 通过明文方式返回给客户端;
-
客户端接收到服务端返回的加密方式后,使用该加密方式生成产生随机码,用作通信过程中 对称加密的密钥 ,使用服务端返回的 公钥进行加密 ,将加密后的随机码发送至服务器;
-
服务器收到客户端返回的加密信息后,使用自己的 私钥进行解密 ,获取 对称加密密钥 。在接下来的会话中,服务器和客户端将会使用该密码进行对称加密,保证通信过程中信息的安全。
2.4 双向验证的流程
双向验证的流程如下图所示:
建立连接的过程:
-
客户端向服务端发送SSL协议版本号、加密算法种类、随机数等信息;
-
服务端给客户端返回SSL协议版本号、加密算法种类、随机数等信息,同时也返回 服务器端的证书 ,即公钥证书;
-
客户端使用服务端返回的信息 验证服务器端的合法性 ,包括:
(1)证书是否过期
(2)颁发服务器证书的CA是否可靠
(3)返回的公钥是否能正确解开返回证书中的数字签名
(4)服务器证书上的域名是否和服务器的实际域名相匹配
验证通过后,将继续进行通信,否则,终止通信;
-
服务端要求客户端发送客户端的证书,客户端会将自己的 证书发送至服务端 ;
-
验证客户端的证书,通过验证后,会获得 客户端的公钥 ;
-
客户端向服务端发送自己所能支持的 对称加密方案 ,供服务器端进行选择;
-
服务器端在客户端提供的加密方案中选择加密程度最高的 加密方式 ;
-
将加密方案通过使用之前获取到的 公钥进行加密 ,返回给客户端;
-
客户端收到服务端返回的加密方案密文后,使用自己的 私钥进行解密 ,获取具体加密方式,而后,产生该加密方式的随机码,用作加密过程中的密钥,使用之前从服务端证书中获取到的公钥进行加密后,发送给服务端;
-
服务端收到客户端发送的消息后,使用自己的私钥进行解密,获取 对称加密的密钥 ,在接下来的会话中,服务器和客户端将会使用该密码进行对称加密,保证通信过程中信息的安全。
3 Springboot整合双向验证
理论知识讲完了,就来实战一下, Springboot
是怎么整合 双向验证 的。
3.1 生成密钥文件
既然是双向验证,就需要双方的密钥,我们服务端称为 localhost ,而客户端称为 client 。需要生成双方的密钥文件,并把对方的 cert 导入自己的密钥文件里。整个过程如下:
注意:密码统一为 changeit
。
# 生成服务端密钥文件localhost.jks keytool -genkey -alias localhost -keyalg RSA -keysize 2048 -sigalg SHA256withRSA -keystore localhost.jks -dname CN=localhost,OU=Test,O=pkslow,L=Guangzhou,C=CN -validity 731 -storepass changeit -keypass changeit # 导出服务端的cert文件 keytool -export -alias localhost -file localhost.cer -keystore localhost.jks # 生成客户端的密钥文件client.jks keytool -genkey -alias client -keyalg RSA -keysize 2048 -sigalg SHA256withRSA -keystore client.jks -dname CN=client,OU=Test,O=pkslow,L=Guangzhou,C=CN -validity 731 -storepass changeit -keypass changeit # 导出客户端的cert文件 keytool -export -alias client -file client.cer -keystore client.jks # 把客户端的cert导入到服务端 keytool -import -alias client -file client.cer -keystore localhost.jks # 把服务端的cert导入到客户端 keytool -import -alias localhost -file localhost.cer -keystore client.jks # 检验服务端是否具有自己的private key和客户端的cert keytool -list -keystore localhost.jks
成功执行完上述步骤后,会生成4个文件:
-
服务端密钥文件: localhost.jks
-
服务端cert文件:localhost.cer
-
客户端密钥文件:client.jks
-
客户端cert文件:client.cer
实际上 cert
文件可以不要了,因为已经导入对方的 Trust Store 里面去了。也就是在文件 localhost.jks
里,包含了服务端的私钥、公钥还有客户端的公钥。 client.jks
同理。
3.2 配置Spirngboot
Springboot
的配置文件如下:
server.port=443 server.ssl.enabled=true server.ssl.key-store-type=JKS server.ssl.key-store=classpath:localhost.jks server.ssl.key-store-password=changeit server.ssl.key-alias=localhost server.ssl.trust-store=classpath:localhost.jks server.ssl.trust-store-password=changeit server.ssl.trust-store-provider=SUN server.ssl.trust-store-type=JKS server.ssl.client-auth=need
需要分别配置 Key Store
和 Trust Store
的文件、密码等信息,即使是同一个文件。
需要注意的是, server.ssl.client-auth
有三个可配置的值: none
、 want
和 need
。双向验证应该配置为 need
; none
表示不验证客户端; want
表示会验证,但不强制验证,即验证失败也可以成功建立连接。
3.3 用Postman测试双向验证
完成密钥文件准备和配置后,启动 Springboot
便可以了。这里用 Postman
访问如下:
无法建立 https
连接,无法访问。原因就是 Postman
作为客户端并没有合法的cert。
为了建立连接,应该要把客户端的密钥文件给 Postman
使用。因为 JKS
是 Java 的密钥文件格式,我们转换成通用的 PKCS12
格式如下:
# 转换JKS格式为P12 keytool -importkeystore -srckeystore client.jks -destkeystore client.p12 -srcstoretype JKS -deststoretype PKCS12 -srcstorepass changeit -deststorepass changeit -srckeypass changeit -destkeypass changeit -srcalias client -destalias client -noprompt
把客户端密钥文件配置到 Postman
如下图所示:
再重新访问,成功了!
或者我们可以把密钥文件拆成 private key
和 cert
,命令如下:
# 导出客户端的cert文件 openssl pkcs12 -nokeys -in client.p12 -out client.pem # 导出客户端的key文件 openssl pkcs12 -nocerts -nodes -in client.p12 -out client.key
把客户端的密钥文件配置到 Postman
上,如图所示:
结果一样是可以成功访问:
3.4 用curl命令测试
没有安装 Postman
怎么办呢?还好,用强大的 curl
命令也是可以测试的。命令如下:
curl -k --cert client.pem --key client.key https://localhost/hello # 下面命令可以查看建立SSL连接详情 curl -v -k --cert client.pem --key client.key https://localhost/hello
如果觉得指定两个文件太麻烦,可以只生成一个文件,命令如下:
openssl pkcs12 -nodes -in client.p12 -out client_all.pem
则连接命令变成了:
# 需要指定密码 curl -k --cert client_all.pem:changeit https://localhost/hello
4 总结
这篇文章讲解了单向验证和双向验证的区别及流程,并用实例展示如何实现双向验证,相信跟着做一遍,基本都能理解了。
参考资料:
Trust Store vs Key Store - creating with keytool
An Overview of One-Way SSL and Two-Way SSL
验证流程部分来自: Https单向认证和双向认证
欢迎访问 南瓜慢说 www.pkslow.com 获取更多精彩文章!
欢迎关注微信公众号< 南瓜慢说 >,将持续为你更新...
多读书,多分享;多写作,多整理。
以上所述就是小编给大家介绍的《Https双向验证与Springboot整合测试-人来人往我只认你》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
.NET设计规范
克瓦林纳 / 葛子昴 / 人民邮电出版社 / 2006-7 / 49.00元
本书为框架设计师和广大开发人员设计高质量的软件提供了权威的指南。书中介绍了在设计框架时的最佳实践,提供了自顶向下的规范,其中所描述的规范普遍适用于规模不同、可重用程度不同的框架和软件。这些规范历经.net框架三个版本的长期开发,凝聚了数千名开发人员的经验和智慧。微软的各开发组正在使用这些规范开发下一代影响世界的软件产品。. 本书适用于框架设计师以及相关的专业技术人员,也适用于高等院校相关专业......一起来看看 《.NET设计规范》 这本书的介绍吧!