項目需要用https與伺服器進行串連,擷取系統需要的一些配置參數。以前是用http進行串連的,用戶端代碼比較簡單,直接使用URL類進行串連並擷取輸入資料流即可。試著在瀏覽器中輸入相應的https串連地址,提示認證確認,確認以後就訪問到內容了。
改成https以後碰到了一些問題。原以為Java可能已經封裝好了,所以把直接把原來的http串連改成https,結果拋出異常:java.lang.UnsupportedClassVersionError: test/url/URLTest (Unsupported major.minor version 49.0)。查了一下,是JVM不支援這個協議(《java網路編程》上有說明)。換了一個jdk,這個問題好了。調用vurl.getProtocol()可以擷取相應的協議了。
接著出現了第二個異常:javax.net.ssl.SSLException: java.lang.RuntimeException: Unexpected error: Java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty。沒辦法,接著google,發現這個問題跟安全連線的認證有關(安全方面的東西不是很瞭解,只知道這個公開金鑰,用於驗證)。查了一下,jdk果然提供了跟認證相關的東西。首先要從伺服器那得到認證,想了一下,ie好像可以。試著用ie串連地址,然後出現了認證確認的提示框,點擊查看認證-詳細資料,點擊複製到檔案,選擇base64編碼,匯出後就可以用記事本開啟了,大概樣子如下:
-----BEGIN CERTIFICATE-----
MIIDITCCAoqgAwIBAgIQS6WuWd7dHMeAfIkikfDiQzANBgkqhkiG9w0BAQQFADBM
MQswCQYDVQQGEwJaQTElMCMGA1UEChMcVGhhd3RlIENvbnN1bHRpbmcgKFB0eSkg
THRkLjEWMBQGA1UEAxMNVGhhd3RlIFNHQyBDQTAeFw0wNjA1MTUyMzE4MTFaFw0w
j8thQJ7StDhAISTBTx/LE0qPlQLfkT3WQOsRb5sQoW/OkV4w9m0TXhWkLsIYngDD
2DJnR/y4HprZmo7M/3wStwO/UiDPIfTzd90SFfCU+pDV41logQ==
-----END CERTIFICATE-----
不用動這個檔案,以後直接匯入即可。
PS:如果已經點擊了認證的確認,可能瀏覽器就直接開啟連結了。這樣情況下,可以接著點擊ie有下腳的“鎖”形符號,即可看見認證。認證搞到手了,接著要然Java環境能夠認識它。這裡調用的是jdk帶的一個exe,keytool.exe(%JAVA_HOME%/bin下有,所以配了java環境變數的話直接能在命令列調用了)。這裡我們輸入匯入命令即可:
%JAVA_HOME%/bin/keytool -import -file service.crt -keystore D:/test/urltest/crt
三個參數分別代表:匯入操作,匯入的認證檔案,匯入認證存放的位置(PS:這個路徑可以使用相對路徑也可以是絕對路徑,但是相對路徑我沒有實驗成功)。匯入處理程序中會提示使用者輸入密碼,這個密碼隨便就行,不過位元不能太少:)
認證是匯入成功了,但是問題ms還是沒解決,新的異常出現了:
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
沒轍,接著google,還好問題不是很麻煩。上面雖然產生了認證,但是還要告訴程式認證的具體位置,涉及一個系統變數要配置。在程式中加入一句話即可:System.setProperty("javax.net.ssl.trustStore","D:/test/urltest/crt");或者在運行java時加入參數:-Djavax.net.ssl.trustStore=D:/test/urltest/crt.
做了這麼多,這個時候是黎明前最黑暗的時候。最後這個問題搞了2小時.......
異常:java.net.UnknownHostException: 222.222.222.222。沒啥好說了的,google。找來找去,找到一個blog說了這麼一句:在產生認證的時候會提示你“你的姓名”,這裡別寫你的名字,而要寫一個ip或者一個你對應網站的網址。拋出的異常提示的錯誤確實是我的https請求中的ip,這樣的話可能是此ip和認證中的“名字”不相同造成的。再次使用ie開啟認證,在“常規”裡面,看到這麼一個東西(我直接用https://mail.google.com試的,因為連它的時候沒有出現任何認證確認)
頒發給:www.google.com
找到url了,開啟我的認證,哈哈,確實也有這麼一個東西,爽。
更鬱悶的來了,url是找到了,可是,此url是個無效的地址.......輸入到ie中返回無法串連。這下知道為什麼google不用確認而這個認證需要確認了。因為此url連不通。怎麼辦?天無絕人之路,還是讓我找到了。其實現在我要做的就是一個網域名稱和ip綁定的問題,但是這個綁定不是DNS來做,而是本機(windows系統)來做。查了一下,果然有,就在C:/WINDOWS/system32/drivers/etc下有一個host檔案,開啟它,可以看到這麼一行
127.0.0.1 localhost
^_^,原來localhost是這樣綁定127.0.0.1的啊,如此就好。我試著加入一行
222.222.222.222 www.sample.test
把原來的https串連的ip換成了那個網域名稱,OK!問題搞定,串連成功。
後記:
在整個調試過程中我一直使用 https://mail.google.com 做為參照來調試。使用這個url的話至於jvm支援,就能直接連接。出現上面的後幾個異常,估計都是與網域名稱有關。因為這個網域名稱是一個DNS不能識別的。
這兩天朋友使用時又發現這樣一個異常:sun.security.validator.ValidatorException: No trusted certificate found 這個異常也是由於沒有找到認證造成的,看看認證的路徑設定對不對