1 简介

不知不觉Https相关的文章已经写了6篇了,本文将是这个专题的最后一篇,起码近期是最后一篇。前面6篇讲的全都是单向的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 总结

这篇文章讲解了单向验证和双向验证的区别及流程,并用实例展示如何实现双向验证,相信跟着做一遍,基本都能理解了。

参考资料:

欢迎关注微信公众号,将持续为你更新...

多读书,多分享;多写作,多整理。

java https双向验证_Https双向验证与Springboot整合测试-人来人往我只认你相关推荐

  1. Https双向验证与Springboot整合测试-人来人往我只认你

    1 简介 不知不觉Https相关的文章已经写了6篇了,本文将是这个专题的最后一篇,起码近期是最后一篇.前面6篇讲的全都是单向的Https验证,本文将重点介绍一下双向验证.有兴趣的同学可以了解一下之前的 ...

  2. java集群解析文件_java相关:springboot整合redis集群过程解析

    java相关:springboot整合redis集群过程解析 发布于 2020-4-13| 复制链接 摘记: 简介 在springboot使用搭建好的redis集群添加redis和连接池依赖 ```x ...

  3. HTTPS实战之单向验证和双向验证

    转载自:https://mp.weixin.qq.com/s/UiGEzXoCn3F66NRz_T9crA 原创: 涛哥 coding涛 6月9日 作者对https 解释的入目三分啊 (全文太长,太懒 ...

  4. HTTPS的SSL单向验证和双向验证

    HTTPS的SSL单向验证和双向验证 ​ HTTPs利用SSL/TLS建立安全信道,加密数据包,主要目的是提供对网站服务器的身份认证,同时保护交换数据的安全性与完整性 SSL/TLS ​ TLS在传输 ...

  5. RFC8705-OAuth 2.0双向TLS客户端身份验证和证书绑定访问令牌

    RFC8705-OAuth 2.0 Mutual-TLS Client Authentication and Certificate-Bound Access Tokens 目录 摘要 1. 简介(I ...

  6. java证书验证失败_Java 跳过 HTTPS 请求过程中证书验证问题

    受益于谷歌和苹果对 HTTPS 的强制升级要求,服务已经全面升级了,安全性提高的同时也引起了新的问题. 由于 HTTPS 证书还是很贵的,所以各种测试环境上各种非法证书,通过浏览器访问的时候可以直接选 ...

  7. JAVA实现发送HTTPS请求(SSL双向认证)

    一.项目背景 Java项目需要作为客户端发起HTTPS请求访问服务端,并且需要携带证书进行SSL双向认证,当前提供的证书相关文件有:ca.crt.ca.key.client.crt.client.ke ...

  8. 实现tomcat的https单向认证及双向认证

    前言 单向认证只需站点部署了ssl证书就行,任何用户都可以去访问(IP被限制除外等),只是服务端提供了身份认证 一般web应用都是采用单向认证的,原因很简单,用户数目广泛,且无需做在通讯层做用户身份验 ...

  9. 【网络】https单向认证和双向认证

    前言 之前面试的时候,面试官问我了解过https的双向认证吗?当时,的确不理解.不过没关系,现在就来补上. 正文 1.单向认证 还是有必要先说下单向认证,单向认证是我刚开始接触https的时候就了解到 ...

  10. Https单向认证和双向认证 认识和区别

    一.Http HyperText Transfer Protocol,超文本传输协议,是互联网上使用最广泛的一种协议,所有WWW文件必须遵循的标准.HTTP协议传输的数据都是未加密的,也就是明文的,因 ...

最新文章

  1. jdk紧急漏洞,XMLDecoder反序列化攻击
  2. Ability的基本概念(2)
  3. List和Set以及Map的选用
  4. 腾讯云短信发送api(SendSms)--java
  5. Java中模拟POST上传文件
  6. python语言绘制词云图
  7. Lanbda表达式 java8新特性
  8. rke 部署的时候报错:Failed to set up SSH tunneling for host
  9. 身份证你需要了解的知识点
  10. 大数据技术系列(1)
  11. 韩顺平--IO流专题
  12. QTP - 29 What’s New in QTP QTP的一些功能介绍
  13. [POI2008]BLO-Blockade,洛谷之提高历练地,强连通分量
  14. 做网站需要多少钱?做网站的费用是多少呢?
  15. coap php 发送,如何使用coap协议向服务器发送数据包
  16. mysql 报错:1140 In aggregated query without GROUP BY, expression #
  17. drupal安装教程mysql_Drupal7安装完整教程
  18. 该用什么软件分割音频?这些软件可以帮助你分割音频
  19. 连接mysql异常Communications link failure
  20. 3d pool ball android,Ball Pool 3D

热门文章

  1. 计算机串口如何应用程序,串口通信调试软件的功能与使用方法 - 全文
  2. 自定义控件1_切换按钮
  3. 计算机中如何隐私保护,隐私保护!我们的电脑该怎么设置开机密码呢?
  4. git pull 报错:Exiting because of unfinished merge.
  5. SpringBoot 开发案例之各种参数传递,以及前端代码和postman测试(完整版)
  6. 深恶痛绝……残忍虐杀何时终止?
  7. 快进来看程序员风格的修真小说!
  8. NBIOT模块学习总结
  9. 报错:Unhandled exception
  10. 蘑菇街面经(自己的第一次秋招面试)