JSSE访问带有未验证证书的HTTPS

2023-11-11

  摘 要JSSE是一个SSL和TLS的纯Java实现,通过JSSE可以很容易地编程实现对HTTPS站点的访问。但是,如果该站点的证书未经权威机构的验证,JSSE将拒绝信任该证书从而不能访问HTTPS站点。本文在简要介绍JSSE的基础上提出了两种解决该问题的方法。

   引言

  过去的十几年,网络上已经积累了大量的Web应用。如今,无论是整合原有的Web应用系统,还是进行新的Web开发,都要求通过编程来访问某些Web页面。传统的方法是使用Socket接口,但现在很多开发平台或工具如.NET、Java或PHP等都提供了简单的Web访问接口,使用这些接口很容易编程实现与Web应用系统的交互访问,即使要访问那些采用了HTTPS而不是HTTP的Web应用系统。

  HTTPS,即安全的超文本传输协议,采用了SSL技术,被广泛使用以保证Web应用系统的安全性。访问Web应用的编程接口大多封装了SSL,使得访问HTTPS和访问HTTP一样简单。但是很多中、小型应用系统或基于局域网、校园网的应用系统所使用的证书并不是由权威的认证机构发行或者被其验证,直接使用这些编程接口将不能访问HTTPS。

  本文将在简要介绍JSSE的基础上,详细描述使用JSSE访问HTTPS的方法,主要说明了如何访问带有未经验证证书的HTTPS站点。

   JSSE简介

  Java安全套接扩展 (Java Secure Socket Extension, JSSE)是实现Internet安全通信的一系列包的集合。它是一个SSL和TLS的纯Java实现,可以透明地提供数据加密、服务器认证、信息完整性等功能,可以使我们像使用普通的套接字一样使用JSSE建立的安全套接字。JSSE是一个开放的标准,不只是Sun公司才能实现一个JSSE,事实上其他公司有自己实现的JSSE。

  在深入了解JSSE之前,需要了解一个有关Java安全的概念:客户端的TrustStore文件。客户端的TrustStore文件中保存着被客户端所信任的服务器的证书信息。客户端在进行SSL连接时,JSSE将根据这个文件中的证书决定是否信任服务器端的证书。

  JSSE中,有一个信任管理器类负责决定是否信任远端的证书,这个类有如下的处理规则:

  ⑴ 果系统属性javax.net.sll.trustStore指定了TrustStore文件,那么信任管理器就去jre安装路径下的lib/security/目录中寻找并使用这个文件来检查证书。

  ⑵ 果该系统属性没有指定TrustStore文件,它就会去jre安装路径下寻找默认的TrustStore文件,这个文件的相对路径为:lib/security/jssecacerts。

  ⑶ 如果 jssecacerts不存在,但是cacerts存在(它随J2SDK一起发行,含有数量有限的可信任的基本证书),那么这个默认的TrustStore文件就是cacerts。

  直接使用类HttpsURLConnection访问Web页面

  Java提供了一种非常简洁的方法来访问HTTPS网页,即使用类HttpsURLConnection、URL等。这几个类为支持HTTPS对JSSE相关类做了进一步的封装,例子如下所示:

URL reqURL = new URL("https://www.sun.com" ); //创建URL对象
HttpsURLConnection httpsConn = (HttpsURLConnection)reqURL.openConnection();

/*下面这段代码实现向Web页面发送数据,实现与网页的交互访问
httpsConn.setDoOutput(true);
OutputStreamWriter out = new OutputStreamWriter(huc.getOutputStream(), "8859_1");
out.write( "……" );
out.flush();
out.close();
*/

//取得该连接的输入流,以读取响应内容
InputStreamReader insr = new InputStreamReader(httpsConn.getInputStream();

//读取服务器的响应内容并显示
int respInt = insr.read();
while( respInt != -1){
 System.out.print((char)respInt);
 respInt = insr.read();
}

  这段代码能够正常执行,然而把访问的URL改为https://login.bjut.edu.cn时,程序将抛出异常javax.net.ssl.SSLException,这是由于https://login.bjut.edu.cn站点的安全证书不被JSSE所信任。根据JSSE简介中对信任管理器的分析,一种解决这个问题的方法是按照信任管理器的处理规则,把站点的证书放到证书库文件jssecacerts中,或者把证书存放到任一TrustStore文件中,然后设置系统属性javax.net.sll.trustStore指向该文件。另一种解决方法则是自己实现信任管理器类,让它信任我们指定的证书。下面分别介绍这两种方法。

   将证书导入到TrustStore文件中

  Java提供了命令行工具keytool用于创建证书或者把证书从其它文件中导入到Java自己的TrustStore文件中。把证书从其它文件导入到TrustStore文件中的命令行格式为:

  keytool -import -file src_cer_file –keystore dest_cer_store

  其中,src_cer_file为存有证书信息的源文件名,dest_cer_store为目标TrustStore文件。

  在使用keytool之前,首先要取得源证书文件,这个源文件可使用IE浏览器获得,IE浏览器会把访问过的HTTPS站点的证书保存到本地。从IE浏览器导出证书的方法是打开“Internet 选项”,选择“内容”选项卡,点击“证书…”按钮,在打开的证书对话框中,选中一个证书,然后点击“导出…”按钮,按提示一步步将该证书保存到一文件中。最后就可利用keytool把该证书导入到Java的TrustStore文件中。为了能使Java程序找到该文件,应该把这个文件复制到jre安装路径下的lib/security/目录中。

  这样,只需在程序中设置系统属性javax.net.sll.trustStore指向文件dest_cer_store,就能使JSSE信任该证书,从而使程序可以访问使用未经验证的证书的HTTPS站点。

  使用这种方法,编程非常简单,但需要手工导出服务器的证书。当服务器证书经常变化时,就需要经常进行手工导出证书的操作。下面介绍的实现X509证书信任管理器类的方法将避免手工导出证书的问题。
  X509证书信任管理器类的实现及应用

  在JSSE中,证书信任管理器类就是实现了接口X509TrustManager的类。我们可以自己实现该接口,让它信任我们指定的证书。

  接口X509TrustManager有下述三个公有的方法需要我们实现:

  ⑴ oid checkClientTrusted(X509Certificate[] chain, String authType)
throws CertificateException

  该方法检查客户端的证书,若不信任该证书则抛出异常。由于我们不需要对客户端进行认证,因此我们只需要执行默认的信任管理器的这个方法。JSSE中,默认的信任管理器类为TrustManager。

  ⑵ oid checkServerTrusted(X509Certificate[] chain, String authType)
throws CertificateException

  该方法检查服务器的证书,若不信任该证书同样抛出异常。通过自己实现该方法,可以使之信任我们指定的任何证书。在实现该方法时,也可以简单的不做任何处理,即一个空的函数体,由于不会抛出异常,它就会信任任何证书。

  ⑶ X509Certificate[] getAcceptedIssuers()

  返回受信任的X509证书数组。

  自己实现了信任管理器类,如何使用呢?类HttpsURLConnection似乎并没有提供方法设置信任管理器。其实,HttpsURLConnection通过SSLSocket来建立与HTTPS的安全连接,SSLSocket对象是由SSLSocketFactory生成的。HttpsURLConnection提供了方法setSSLSocketFactory(SSLSocketFactory)设置它使用的SSLSocketFactory对象。SSLSocketFactory通过SSLContext对象来获得,在初始化SSLContext对象时,可指定信任管理器对象。下面用一个图简单表示这几个JSSE类的关系:

点击看大图
图1 部分JSSE类的关系图
  假设自己实现的X509TrustManager类的类名为:MyX509TrustManager,下面的代码片断说明了如何使用MyX509TrustManager:

//创建SSLContext对象,并使用我们指定的信任管理器初始化
TrustManager[] tm = {new MyX509TrustManager ()};
SSLContext sslContext = SSLContext.getInstance("SSL","SunJSSE");
sslContext.init(null, tm, new java.security.SecureRandom());

//从上述SSLContext对象中得到SSLSocketFactory对象
SSLSocketFactory ssf = sslContext.getSocketFactory();

//创建HttpsURLConnection对象,并设置其SSLSocketFactory对象
HttpsURLConnection httpsConn = (HttpsURLConnection)myURL.openConnection();
httpsConn.setSSLSocketFactory(ssf);

  这样,HttpsURLConnection对象就可以正常连接HTTPS了,无论其证书是否经权威机构的验证,只要实现了接口X509TrustManager的类MyX509TrustManager信任该证书。

   小结

  本文主要介绍了在HTTPS的证书未经权威机构认证的情况下,访问HTTPS站点的两种方法,一种方法是把该证书导入到Java的TrustStore文件中,另一种是自己实现并覆盖JSSE缺省的证书信任管理器类。两种方法各有优缺点,第一种方法不会影响JSSE的安全性,但需要手工导入证书;第二种方法虽然不用手工导入证书,但需要小心使用,否则会带来一些安全隐患。
 
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

JSSE访问带有未验证证书的HTTPS 的相关文章

随机推荐

  • qt实现QLabel上显示的文字有描边

    qt实现文字描边 效果图 开发环境 项目示例 综述 效果图 此程序运行的效果 开发环境 1 关于我的开发环境 我目前有点迷惑 我的QtCreator中帮助 关于QtCreator 得到如下所示 但是我的安装包上却写着5 12 9 我的理解就
  • Bash 脚本 set 命令教程

    转自 http www ruanyifeng com blog 2017 11 bash set html utm source tool lu 服务器的开发和管理离不开 Bash 脚本 掌握它需要学习大量的细节 set命令是 Bash 脚
  • 在自己电脑上的idea运行java web项目 如何用外网访问

    目的 本人目前Android开发比如手机的销售统计激活数据上传 自己先写一个网络接口测试等后端写好了换上去就行 用自己的电脑当作服务器 使用IntelliJ IDEA 创建一个springboot 部署在自己电脑上 使用手机请求网络接口 或
  • ddt数据驱动常见的用法【多测师_王sir】

    一 背景 一般进行接口测试时 每个接口的传参都不止一种情况 一般会考虑正向 逆向等多种组合 所以在测试一个接口时 通常会编写多条case 而这些除了传参不同外 并没有什么区别 这个时候就可以利用ddt来管理测试数据 提高代码复用率 二 dd
  • 2017今日头条网招在线编程题(部分)

    第一题 P 为 给 定 的 二 维 平 面 整 数 点 集 定 义 P 中 某 点 如 果 满 足 P 中 任 意 点 都 不 在 的 右 上 方 区 域 内 横 纵 坐标 都 大 于 则 称 其 为 最 大 的 求 出 所 有 最 大 的
  • 牛客-困难及极难难度python

    1 字符串最后一个单词的长度 计算字符串最后一个单词的长度 单词以空格隔开 字符串长度小于5000 def get length input str input str list input str strip split if len s
  • 高并发内存池项目(concurrent memory pool)

    一 高并内存池概念 内存池 Memory Pool 是一种动态内存分配与管理技术 通常情况下 程序员习惯直接使用 new delete malloc free 等API申请分配和释放内存 这样导致的后果是 当程序长时间运行时 由于所申请内存
  • Git使用方法笔记1——Git

    git 安装包 源 https npm taobao org mirrors git for windows v2 22 0 windows 1 一 Git基本操作 查看git安装路径 where git 1 设置本地系统用户名和邮箱 gi
  • 基于ArcGIS的nc(NETCDF)转tif格式

    软件版本 ArcMap10 4 1 nc NETCDF 是一组独立于机器的软件库支持创建 访问和共享面向阵列的数据格式科学数据 它也是共享科学数据的社区标准 摘自Unidata官网 被广泛应用于大气 海洋 水文等领域 是我们日常学习和工作中
  • LVM 磁盘结构

    复杂度3 5 机密度4 5 最后更新2021 05 17 VG由一堆PV组成 每个PV的头是ipl rec 无论这个PV能不能boot 只要是AIX的盘 曾经标记过PVID 都在最初0字节标记0xc9c2d4c1 这个是EBCIDIC编码的
  • c++ 代码连接激光雷达,使用 pybind11 得到python模块,可以直接在python中连接雷达,获取 numpy 格式激光数据

    注意 这个程序最后需要编译为 python 的一个模块 然后导入python中使用 底层原理是python调用c 程序连接激光雷达 然后把获取的数据转换为numpy格式 因为用python太慢了 C 函数 用于获取一个帧的数据并将其转换为P
  • 【leetcode】Java 力扣第一题(两数之和)简单

    废话不多说 直接上干货 Leetcode每日一题 2021 10 18开启 有的人夜里去看海 有的人力扣第一题就做不出来 犹记得那次在刘老师强推下开了力扣的刷题之旅 用打开力扣APP 第一题 选择简单模式 轻车熟路 啧啧啧 给定一个整数数组
  • 使用apifox前置数据base64编码并添加一个字段

    具体前置脚本如下 pm request body update 处理 body 参数里的变量 let bodyStr pm request body raw base64 编码数据 let bodyEncode btoa bodyStr c
  • 单片机学习笔记-如何计算数码管段码

    如何计算数码管段码 转自百度知道 https jingyan baidu com article 20b68a88f2c3bf796dec625f html 我们在使用数码管的时候 不可避免地要用到数码管的段码 没有段码那么我们就不能正确的
  • 2023数学建模国赛游记

    第一参加数学建模国赛 大概也是最后一次参加了 记录一下这几天的历程吧 我们队的情况是计算机 电气 数统 计算机负责编程 电气学院的负责论文部分 数统的同学负责建模 数据处理部分我们是共同承担 第一天下午6点发题 5点学校的所有队伍基本都到管
  • 产品经理修炼手册—上瘾

    现在的人们越来越喜欢用上瘾某款应用来形容一个人了 比如对游戏上瘾 对网上购物上瘾等 这次想来整理一下关于如何让用户喜欢也就是上瘾一款产品的步骤 当然 需要让大家理解一些前提 首先是 产品分为维生素和止痛药 顾名思义 维生素是吃下去但是并不知
  • QT 在信号草里面刷新控件立即生效的办法:qApp->processEvents();

    void setdid on lbt start set did clicked ui gt lln set did result gt setText ui gt lln apiLicence gt setText qApp gt pro
  • 单目标应用:基于麻雀搜索算法优化灰色神经网络(grey neural network)的数据预测(提供MATLAB代码)

    一 麻雀搜索算法 麻雀搜索算法 sparrow search algorithm SSA 由Jiankai Xue等人于2020年提出 该算法是根据麻雀觅食并逃避捕食者的行为而提出的群智能优化算法 SSA 主要是受麻雀的觅食行为和反捕食行为
  • flink 1.9.0 编译:flink-fs-hadoop-shaded 找不到

    1 编译 lcc lcc flink mvn clean install Dmaven test skip true Dhadoop version 2 8 3 Dmaven javadoc skip true Dcheckstyle sk
  • JSSE访问带有未验证证书的HTTPS

    摘 要JSSE是一个SSL和TLS的纯Java实现 通过JSSE可以很容易地编程实现对HTTPS站点的访问 但是 如果该站点的证书未经权威机构的验证 JSSE将拒绝信任该证书从而不能访问HTTPS站点 本文在简要介绍JSSE的基础上提出了两