首页 > 编程语言 >JAVA中HTTPS那些事儿

JAVA中HTTPS那些事儿

时间:2024-03-21 16:24:17浏览次数:45  
标签:JAVA 证书 hostname 校验 SSL TrustStore HTTPS 事儿

转载自:https://www.jianshu.com/p/20180ca83012

本章是HTTPS那些事儿的第二篇文章,其他相关文章请参见:前言
本篇主要描述JAVA中与HTTPS相关的概念与代码实现。

  • JAVA中的证书
  • KeyStore和TrustStore
  • SSL层证书校验过程
  • HttpsURLConnection

* 注意

本文纯手工打造,转载请注明出处。

JAVA中的证书

Java在JRE的安装目录中保存了一份默认可信的证书列表,这个列表保存在$JRE/lib/security/cacerts文件中,可以通过JRE自带的keytool工具打开该文件,默认密码为changeit。可以通过如下命令列出cacerts中的所有内容:

keytool -list -keystore cacerts

回车后可以看到如下内容:


  cacerts内容

这里显示的是简略内容,如果需要查看RFC格式的输出,可以添加rfc参数,也就是:

keytool -list -rfc -keystore cacerts

还可以查看确定某一项的的详细信息,只需要加上-alias-v参数即可。

KeyStore和TrustStore

我们所说的cacert文件其实是一个KeyStore文件,KeyStore文件可以存放数字证书、对称密钥等信息,这里所述的KeyStore只是一种文件格式。
java中的KeyStore这种文件可以分为两类:KeyStore和TrustStore。KeyStore保存私钥,在加解密、签名时使用。TrustStore保存可信任的证书,用于对被访问者进行认证。所以准确的来说cacerts文件其实应该属于TrustStore
对应于KeyStore和TrustStore,Java中有两个类:KeyManager 和 TrustManager。在JSSE 的参考手册中有一张示意图,说明了java中https实现的各个类之间的关系:

  java中SSL层类图
可以看出如果要进行 SSL 会话,必须得新建一个 SSLSocket 对象,而 SSLSocket 对象是通过 SSLSocketFactory 来管理的,SSLSocketFactory 对象则依赖于 SSLContext ,SSLContext 对象又依赖于 keyManager、TrustManager 和 SecureRandom。而这里面的TrustManager就是负责对网站进行认证,校验其CA证书是否合法的。

 

SSL/TSL层证书校验过程

知道了JAVA中的https相关的类之后,我们就可以来分析JAVA中的https认证过程了,https的认证过程其实就是SSL/TSL的认证过程。
1. 初始化阶段
初始化SSLContext时会将TrustStore中的所有证书加载进来。TrustManagerFactoryImpl.getCacertsKeyStore()方法负责加载证书,首先查找$JRE/lib/security/jssecacerts文件是否存在,如果不存在则加载$JRE/lib/security/cacerts文件。如果都不存在,则使用空的TrustStore,这样的话不会有服务器的CA证书被校验通过。
2. 创建TrustManage
在TrustStore加载完毕后,会初始化TrustManager,默认使用实现类X509TrustManagerImpl。该类在构造方法中会调用KeyStores.getTrustedCerts(KeyStore)方法将TrustStore中的证书加载成X509Certificate证书。
3. checkServerTrusted
初始化后,客户端会与服务器端建立连接,然后进入Handshake过程,当拿到服务器端的CA证书时,会调用X509TrustManager. checkServerTrusted(…)方法,该方法完成实际的证书校验:
a).校验域名/IP
校验访问地址中的域名/IP(要么域名,要么IP)是否与服务器证书包含的一致,使用到HostnameChecker. match方法进行。如果访问使用的是域名,但服务器CA证书中没有包含域名,则抛出错误:

No subject alternative DNS name matching localhost found //其中localhost表示域名。

如果访问使用的是IP,但服务器CA证书中没有IP,则抛出错误:

No subject alternative names present

如果域名不匹配抛出错误:

No name matching localhost found //其中localhost表示域名。

如果IP不匹配,则抛出错误:

No subject alternative names matching IP address 127.0.0.1 found //其中127.0.0.1表示ip。

b). 服务器证书是否可信
通过加载的TrustStore证书来校验服务器的证书是否由信任的证书机构颁发,使用到方法PKIXValidator.engineValidate()。该校验过程如果失败,则抛出类似如下错误:

PKIX path building failed: 
        sun.security.provider.certpath.SunCertPathBuilderException: 
            unable to find valid certification path to requested target

HttpsUrlConnection

java中访问HTTP服务时,会使用到HttpURLConnection,而如果访问的是HTTPS则会使用HttpsURLConnection。相关类图如下:

  Http相关类图
可以看出如果访问的是Http,则使用HttpURLConnection,该类使用HttpClient完成实际的网络请求。如果访问的是HTTPS,则会使用HttpsURLConnection,同样会使用对应的HttpsClient。HttpsURLConnection的实现类HttpsURLConnectionImpl中会使用到两个类,HostnameVerifier和SSLSocketFactory。这两个类是实现HTTPS请求的核心,通过配置这两个类可以影响SSL层校验域名/IP和服务器证书校验的过程。可以通过HttpsURLConnection.SetDefaultSSLSocketFactory和HttpsURLConnection.SetDefaultHostnameVerifier来设置,后续会有代码示例。

 

HostnameVerifier

根据上一小节SSL/TSL层证书校验过程所述,在SSL/TLS层面已经会校验hostname了,而在HTTPS层我们同样有HostnameVerifier来校验hostname,为什么呢?其实二者之间是合作关系,HTTPS层的会影响SSL/TLS层的逻辑,他们的关系可以通过如下表格来表示:

  HTTPS与SSL层Hostname校验器关系

 

  • EIA algorithm表示SSL/TLS层面的校验,SSL层面可以通过如下方法进行设置:
SSLParameters.setEndpointIdentificationAlgorithm(String)

可设置三个值null,HTTPS和LDAP/其他。

  • HNV表示HTTPS层面的HostnameVerifier,HNV可以通过方法HttpsURLConnection.setDefaultHostnameVerifier(obj)进行设置,如果不设置则表中的值为defualt,如果设置了,则值为non-default。defualt的实现类为DefaultHostnameVerifier,该类为HttpsURLConnectionImpl的静态内部类。
    case1: default HNV and EIA is null
    结果是设置SSL/TSL层为HTTPS,仅由SSL/TLS层进行hostname校验(JDK中默认使用的是该规则)。
    case 2: default HNV and EIA is HTTPS
    结果是使用SSL/TSL层的值HTTPS,仅由SSL/TLS层进行hostname校验
    case 3: default HNV and EIA不是HTTPS
    结果是SSL/TLS层使用设置的值LDAP/其他进行校验,而hostname则在HTTPS层使用默认的DefaultHostnameVerifier校验
    case 4: non-default HNV and EIA is null
    SSL/TLS层不做任何校验,HTTPS层使用设置的HNV规则校验hostname
    case 5: non-default HNV and EIA is HTTPS
    结果是使用EIA algorithm的值,由SSL/TLS层进行hostname校验。该情况下不允许在HTTP层进行校验。
    case 6: non-default HNV and EIA不是HTTPS
    结果是SSL/TLS层使用设置的值LDAP/其他进行校验,而hostname则在HTTPS层使用设置的HNV规则校验hostname

SSLSocketFactory

SSLSocketFactory是负责SSL层面校验hostname、客户端证书和服务器证书的SSLSocket的工厂,默认情况下HttpsURLConnectionImpl中会获取默认的SSLSockectFactory,默认的factory会使用X509TrustManagerImpl来执行hostname和证书的校验,校验规则参考前一小节SSL/TSL层证书校验过程

总结

本篇从java中TrustStore和KeyStore入手,深入到JAVA中的SSL和HTTPS相关实现类。分析了,java中比较核心的几个类。后续文章,会介绍java中使用HTTPS经常遇到的场景:不校验服务器证书

标签:JAVA,证书,hostname,校验,SSL,TrustStore,HTTPS,事儿
From: https://www.cnblogs.com/wanghengbin/p/18087652

相关文章

  • 前端基础之JavaScript流程控制
    一、if判断在JavaScript中,if语句是一种常见的条件语句,用于根据条件执行不同的代码块。除了基本的if语句外,还有if...else、if...elseif...else等变体,用于处理多个条件的情况。1.if语句if语句用于在条件为真时执行特定的代码块。语法:if(condition){//当条件......
  • 前端基础之JavaScript对象
    一、什么是对象现实生活中:万物皆对象,对象是一个具体的事物,看得见摸得着的实物。例如,一本书、一辆汽车、一个人可以是“对象”,一个数据库、一张网页、一个与远程服务器的连接也可以是“对象”。在JavaScript中,对象是一组无序的相关属性和方法的集合,所有的事物都是对象,例如字......
  • 前端基础之JavaScript函数
    一、什么是函数在JavaScript中,函数是一种可重复使用的代码块,用于执行特定任务或计算。函数可以接受参数,执行特定的操作,并返回一个值。二、函数的声明函数可以通过函数声明、函数表达式或箭头函数来定义。函数声明:functionfunctionName(parameters){//函数体......
  • JavaScript 实现通过 id 数组获取可展示的 name 拼接字符串
    JavaScript实现通过id数组获取可展示的name拼接字符串场景有一个包含许多对象的数组,每个对象都包含了一个标识(id)和一个名称(name)。想要从这个数组中选出特定的一些对象,这些对象的标识(id)在另一个数组中已经给出。然后,想把这些选出来的对象的名称(name)连接成一个字符串,用逗号分......
  • java社团管理系统app(ssm框架毕业设计)
    本系统(程序+源码)带文档lw万字以上  文末可领取本课题的JAVA源码参考系统程序文件列表系统的选题背景和意义选题背景:随着互联网技术的飞速发展,社团活动在校园文化中扮演着日益重要的角色。学生社团作为大学生活的重要组成部分,不仅丰富了学生的课余生活,还提供了展示才华、......
  • java社团信息管理系统(ssm框架毕业设计)
    本系统(程序+源码)带文档lw万字以上  文末可领取本课题的JAVA源码参考系统程序文件列表系统的选题背景和意义选题背景:在现代社会,社团作为校园文化的重要组成部分,承载着培养学生兴趣、拓展知识领域和提升实践能力的重要使命。随着教育理念的更新和学生需求的多样化,社团活动......
  • Java22重磅发布!!!!卷不动了,真的卷不动了。。。。
    就在3月19日,Java22重磅发布。Java22新增了12项增强功能,其中包括七个预览特性和一个孵化器特性,这些功能都显著到足以引起JDK增强提案(JEPs)的关注。它们涵盖了Java语言、其API、性能以及JDK中包含的工具的改进。真的卷不动了,,前段时间才将项目升级到Java17。。。。接下来我们看看具......
  • HTTPS的过程
       主要有发起请求、验证身份、协商秘钥、加密会话4大步骤    1)客户端向服务端发起建立HTTPS请求。   2)服务器向客户端发送数字证书。   3)客户端验证数字证书,证书验证通过后客户端生成会话密钥(双向验证则此处客户端也会向服务器发送证书)。   4)......
  • 【干货】Java开发者快速上手.NET指南
    前言前几天有小伙伴在技术群里发了一个微软官方出的:适用于Java开发人员的.NET快速入门免费电子书,今天大姚来分享一下Java开发者想要快速上手.NET有哪些教程和优质资料。微软适用于Java开发人员的.NET快速入门指南下载阅读地址:https://dotnet.microsoft.com/zh-cn/campaigns/do......
  • Java学习笔记——第二十二天
    Java高级技术单元测试概述单元测试就是针对最小的功能单元(方法),编写测试代码对该功能进行正确性测试。目前的测试方法是怎样的,存在什么问题只能编写main方法,并在main方法中再去调用其他方法进行测试。使用起来很不灵活,无法实现自动化测试。无法得到测试的报告,需要程序员......