java实现的https请求
Https请求
超⽂本传输协议HTTP协议:被⽤于在Web浏览器和⽹站服务器之间传递信息。HTTP协议以明⽂⽅式发送内容,不提供任何⽅式的数据加密,如果攻击者截取了Web浏览器和⽹站服务器之间的传输报⽂,就可以直接读懂其中的信息,因此HTTP协议不适合传输⼀些敏感信息,⽐如信⽤卡号、密码等。
为了解决HTTP协议的这⼀缺陷,需要使⽤另⼀种协议:安全套接字层超⽂本传输协议HTTPS。为了数据传输的安全,HTTPS在HTTP的基础上加⼊了SSL协议,SSL依靠证书来验证服务器的⾝份,并为浏览器和服务器之间的通信加密。
HTTPS和HTTP的区别主要为以下四点:
⼀、https协议需要到CA申请证书,⼀般免费证书很少,需要交费。
⼆、http是超⽂本传输协议,信息是明⽂传输,https 则是具有安全性的ssl加密传输协议。
三、http和https使⽤的是完全不同的连接⽅式,⽤的端⼝也不⼀样,前者是80,后者是443。
四、http的连接很简单,是⽆状态的;HTTPS协议是由SSL+HTTP协议构建的可进⾏加密传输、⾝份认证的⽹络协议,⽐http协议安全。
>>> JSSE简介
  Java安全套接扩展 (Java Secure Socket Extension, JSSE)是实现Internet安全通信的⼀系列包的集合。它是⼀个SSL和TLS的纯Java实现,可以透明地提供数据加密、服务器认证、信息完整性等功能,可以使我们像使⽤普通的套接字⼀样使⽤JSSE建⽴的安全套接字。JSSE 是⼀个开放的标准,不只是Sun公司才能实现⼀个JSSE,事实上其他公司有⾃⼰实现的JSSE。
  在深⼊了解JSSE之前,需要了解⼀个有关Java安全的概念:客户端的TrustStore⽂件。客户端的TrustStore⽂件中保存着被客户端所信任的服务器的证书信息。客户端在进⾏SSL连接时,JSSE将根据这个⽂件中的证书决定是否信任服务器端的证书。
  JSSE中,有⼀个信任管理器类负责决定是否信任远端的证书,这个类有如下的处理规则:
  ⑴如果系统属性ustStore指定了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("www.sun" ); //创建URL对象
HttpsURLConnection httpsConn = (HttpsURLConnection)reqURL.openConnection();
/*下⾯这段代码实现向Web页⾯发送数据,实现与⽹页的交互访问
httpsConn.setDoOutput(true);
OutputStreamWriter out = new OutputStream(), "8859_1");
out.write( "……" );
out.flush();
out.close();
*/
//取得该连接的输⼊流,以读取响应内容
InputStreamReader insr = new InputStream();
//读取服务器的响应内容并显⽰
int respInt = ad();
while( respInt != -1){
 System.out.print((char)respInt);
 respInt = ad();
}
>>> 将证书导⼊到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/⽬录中。
  这样,只需在程序中设置系统属性ustStore指向⽂件dest_cer_store,就能使JSSE信任该证书,从⽽使程序可以访问使⽤未经验证的证书的HTTPS站点。
  使⽤这种⽅法,编程⾮常简单,但需要⼿⼯导出服务器的证书。当服务器证书经常变化时,就需要经常进⾏⼿⼯导出证书的操作。下⾯介绍的实现X509证书信任管理器类的⽅法将避免⼿⼯导出证书的问题。
>>> X509证书信任管理器类的实现及应⽤
  在JSSE中,证书信任管理器类就是实现了接⼝X509TrustManager的类。我们可以⾃⼰实现该接⼝,让它信任我们指定的证书。
  接⼝X509TrustManager有下述三个公有的⽅法需要我们实现:
  ⑴ void checkClientTrusted(X509Certificate[] chain, String authType)
throws CertificateException
  该⽅法检查客户端的证书,若不信任该证书则抛出异常。由于我们不需要对客户端进⾏认证,因此我们只需要执⾏默认的信任管理器的这个⽅法。JSSE中,默认的信任管理器类为TrustManager。
  ⑵ void 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 = Instance("SSL","SunJSSE");
sslContext.init(null, tm, new java.security.SecureRandom());
//从上述SSLContext对象中得到SSLSocketFactory对象
SSLSocketFactory ssf = SocketFactory();
//创建HttpsURLConnection对象,并设置其SSLSocketFactory对象
HttpsURLConnection httpsConn = (HttpsURLConnection)myURL.openConnection();
httpsConn.setSSLSocketFactory(ssf);
  这样,HttpsURLConnection对象就可以正常连接HTTPS了,⽆论其证书是否经权威机构的验证,只要实现了接⼝X509TrustManager 的类MyX509TrustManager信任该证书。java创建文件
  ⼩结
  本⽂主要介绍了在HTTPS的证书未经权威机构认证的情况下,访问HTTPS站点的两种⽅法,⼀种⽅法是把该证书导⼊到Java的TrustStore⽂件中,另⼀种是⾃⼰实现并覆盖JSSE缺省的证书信任管理器类。
两种⽅法各有优缺点,第⼀种⽅法不会影响JSSE的安全性,但需要⼿⼯导⼊证书;第⼆种⽅法虽然不⽤⼿⼯导⼊证书,但需要⼩⼼使⽤,否则会带来⼀些安全隐患。