程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> 關於JRE 1.6 HTTPS請求出錯的問題,jrehttps

關於JRE 1.6 HTTPS請求出錯的問題,jrehttps

編輯:JAVA綜合教程

關於JRE 1.6 HTTPS請求出錯的問題,jrehttps


最近在用java請求內部的一個HTTP接口,URL是HTTPS加密形式的,大致的代碼是這樣的:

  1 public String sendGet(String url) {
  2         String result = "";
  3         BufferedReader in = null;
  4         try {
  5             String urlNameString = url ;
  6             URL realUrl = new URL(urlNameString);
  7             // 打開和URL之間的連接
  8             URLConnection connection = realUrl.openConnection();
  9             // 設置通用的請求屬性
 10             connection.setRequestProperty("accept", "*/*");
 11             connection.setRequestProperty("connection", "Keep-Alive");
 12             connection.setRequestProperty("user-agent",
 13                     "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
 14             // 建立實際的連接
 15             connection.connect();
 16 
 17             // 定義 BufferedReader輸入流來讀取URL的響應
 18             in = new BufferedReader(new InputStreamReader(
 19                     connection.getInputStream(),"utf-8"));
 20             String line;
 21             while ((line = in.readLine()) != null) {
 22                 result += line;
 23             }
 24         } catch (Exception e) {
 25 
 26             e.printStackTrace();
 27         }
 28         // 使用finally塊來關閉輸入流
 29         finally {
 30             try {
 31                 if (in != null) {
 32                     in.close();
 33                 }
 34             } catch (Exception e2) {
 35                 e2.printStackTrace();
 36             }
 37         }
 38         return result;
 39     }

從tomcat的日志來看,拋出的異常如下:

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

從谷歌的一些搜索來看,基本都建議使用keytool導入CA證書,例如:

Resolving javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed Error?

發現這種方法並沒有解決我的問題,而且HTTPS URL對應的證書是從GoDaddy購買的正規證書,應該不存在JRE不信任的問題。

直到搜索到這篇文章:解決PKIX:unable to find valid certification path to requested target 的問題

雖然方法大同小異,但通過執行編譯後的文件發現:並不是服務器真實的證書啊!

域名、證書都不是,第一反應:我的服務器被黑啦?趕緊Wireshark抓包,結果證明確實是服務器返回的證書,這就更奇怪了

由於HTTPS的接口是部署在CDN上的,所以趕緊聯系CDN廠商反饋問題,CDN廠商那邊反復確認他們那邊沒有問題,一切正常。

又開始懷疑自己是否遭到了SSL中間人攻擊,反復確認沒有問題。在排查的過程中發現兩個現象:

1、上圖中的域名對應的IP就是我們CDN廠商的IP,也就是說 和我們使用同一家CDN,浏覽器打開他們的網站,證書也完全吻合。

2、在一台WIN 2003上分別用FF和IE 7訪問HTTPS接口站點,FF的證書是正常的,IE7的證書和上圖中的是一致(即:錯誤的證書)。

基本可以判斷要麼CDN那邊返回錯了,要麼客戶端請求的時候有什麼東西發錯了。突然想到虛擬主機(一個IP同一個端口部署多個站點)的原理,就是根據HTTP HEADER中HOST參數來區分。那SSL怎麼實現不同的域名返回不同的證書呢?

直到發現了一個叫SNI(Server Name Indication)的概念,主要的作用是允許在相同的IP地址和TCP端口號的服務器上使用多個證書,而不必所有網站都使用同一個證書。在概念上等同於HTTP/1.1基於域名的虛擬主機,只不過這是在HTTPS上實現的。

更重要的是JRE從1.7版本才開始支持SNI,而我tomcat服務器上的JRE為1.6版本,不支持SNI。原因找到了,果斷升級到最新的1.8版本,重啟tomcat,問題立馬解決~

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved