导入https证书

本文介绍在HTTPS的证书未经权威机构认证的情况下,如何通过导入证书到Java的TrustStore文件或自定义信任管理器类来访问HTTPS站点。包括使用SSLContext设置信任管理器和相关JSSE类的关系图,以及两种方法的优缺点比较。

[转自] http://www.blogjava.net/etlan/archive/2006/06/29/55767.html


摘 要 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的安全性,但需要手工导入证书;第二种方法虽然不用手工导入证书,但需要小心使用,否则会带来一些安全隐患。
<think>好的,我现在需要帮助用户了解如何将HTTPS证书导入JDK中。首先,我应该回忆一下之前用户提供的引用内容,这些引用提到了不同系统下的操作步骤,包括Windows和Linux,还有一些注意事项,比如证书名称唯一性、路径问题以及命令的具体参数。用户现在的问题是明确的,但需要结构清晰的步骤说明,并且要符合系统级指令中的格式要求,比如使用中文回答、正确使用LaTeX、生成相关问题等。 首先,我需要整理导入证书的基本步骤,分为Windows和Linux两部分,因为引用中提到了这两种系统的不同路径和命令。同时,需要注意每个步骤中的关键点,比如导出证书、保存路径、keytool命令的正确使用,以及最后的验证步骤。 然后,要确保所有行内公式和代码块都正确使用$...$或```格式。例如,命令中的路径可能需要使用代码块来展示,而变量或参数可能需要用行内代码。另外,引用需要自然地插入到对应的步骤后面,比如提到证书名称唯一性时引用[^2],或者在Linux路径时引用[^3]。 接下来,生成相关问题需要考虑用户可能遇到的后续疑问,比如验证是否成功、不同JDK版本的影响、证书格式问题等。这些问题应该基于导入过程中的关键步骤和常见问题点来设计。 最后,需要检查整个回答是否符合用户的要求,结构是否清晰,步骤是否详细,并且确保引用正确。同时,要避免使用Markdown格式,保持自然的中文表达,并确保所有技术术语和命令准确无误。</think>### 分步说明:JDK中导入HTTPS证书的步骤 #### 一、导出证书文件 1. 在浏览器中访问目标HTTPS网站(如`https://example.com`),点击地址栏锁形图标,选择**导出证书**或**保存证书**。 2. 将证书保存为`.cer`或`.crt`格式,例如`mycert.cer`。需确保文件名唯一,避免与JDK已有证书重复。 #### 二、Windows系统操作步骤 1. **定位JDK安全目录** 证书导入到`%JAVA_HOME%/jre/lib/security/cacerts`文件中。例如JDK 1.8的典型路径为: ``` C:\Program Files\Java\jdk1.8.0_291\jre\lib\security ``` 2. **执行导入命令** 打开CMD,切换到证书所在目录(或指定证书路径),执行: ```shell keytool -import -alias my_cert -keystore "%JAVA_HOME%/jre/lib/security/cacerts" -file mycert.cer ``` 默认密码为`changeit`,操作完成后需确认输入`y`[^1][^2]。 #### 三、Linux系统操作步骤 1. **复制证书到安全目录** 将证书文件上传至服务器,例如存放路径为`/opt/certs/mycert.cer`。 2. **执行导入命令** 使用以下命令(注意替换实际JDK路径): ```shell keytool -import -alias linux_cert -keystore "/usr/local/jdk1.8.0_301/jre/lib/security/cacerts" -file /opt/certs/mycert.cer ``` 输入密码`changeit`并确认操作[^3]。 #### 四、验证导入结果 执行查询命令检查证书是否成功添加: ```shell keytool -list -keystore cacerts -alias my_cert ``` 若输出包含指定别名(如`my_cert`),则表明导入成功[^3]。 #### 五、配置Tomcat(如需) 若需在Tomcat中使用该证书,需在`server.xml`中指定密钥库路径: ```xml <Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol" keystoreFile="conf/tomcat.keystore" keystorePass="password"/> ``` 注意:此步骤仅在使用自定义密钥库时需配置[^4]。 ### 关键注意事项 1. **JDK版本差异** JDK 9及以上版本改用`$JAVA_HOME/lib/security/cacerts`路径,需注意路径调整。 2. **证书格式兼容性** Keytool仅支持`.cer`、`.crt`或`.pem`格式,若为`.pfx`需先转换格式。 3. **别名冲突处理** 若提示`Alias already exists`,需先删除旧证书: ```shell keytool -delete -alias old_cert -keystore cacerts ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值