1. Https原理
SSL(Secure Sockets Layer 安全套接層),為網景公司(Netscape)所研發,用以保障在 Internet 上數據傳
輸之安全,利用數據加密(Encryption)技術,可確保數據在網絡上之傳輸過程中不會被截取及竊聽。一般通
用之規格為 40 bit 之安全標準,美國則已推出 128 bit 之更高安全標準,但限制出境。只要 3.0 版本以上之
I.E.或 Netscape 瀏覽器即可支持 SSL。
TLS(Transport Layer Security 傳輸層安全),用于在兩個通信應用程序之間提供保密性和數據完整性。
TLS 是 SSL 的標準化后的產物,有 1.0 ,1.1 ,1.2 三個版本,默認使用 1.0。TLS1.0 和 SSL3.0 幾乎沒
有區別 ,事實上我們現在用的都是 TLS,但因為歷史上習慣了 SSL 這個稱呼。
SSL 通信簡單圖示:

SSL 通信詳細圖示:

當請求使用自簽名證書的網站數據時,例如請求 12306 的客運服務頁面:https://kyfw.12306.cn/otn/,
則會報下面的錯誤,原因是客戶端的根認證機構不能識別該證書。

2. 獲取https網頁源碼
下面我們演示在不使用證書的情況下,獲取12306的網頁(https協議)。
~~~
1. package com;
2.
3. import java.io.ByteArrayOutputStream;
4. import java.io.IOException;
5. import java.io.InputStream;
6. import java.net.MalformedURLException;
7. import java.net.URL;
8. import java.security.KeyManagementException;
9. import java.security.NoSuchAlgorithmException;
10. import java.security.cert.CertificateException;
11. import java.security.cert.X509Certificate;
12.
13. import javax.net.ssl.HttpsURLConnection;
14. import javax.net.ssl.SSLContext;
15. import javax.net.ssl.TrustManager;
16. import javax.net.ssl.X509TrustManager;
17.
18. public class Https {
19. public static void main(String[] args) throws NoSuchAlgorithmException, KeyManagementException,
20. IOException {
21. SSLContext sslContext = SSLContext.getInstance("TLS");
22. TrustManager[] tm = new TrustManager[]{new EmptyTrustManager()};
23. sslContext.init(null, tm, null);
24. HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
25. URL url = new URL(“https://kyfw.12306.cn/otn");
26. HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
27. InputStream is = connection.getInputStream();
28. ByteArrayOutputStream baos = new ByteArrayOutputStream();
29. int len;
30. byte[] buffer = new byte[1024];
31. while((len=is.read(buffer))!=-1){
32. baos.write(buffer, 0, len);
33. }
34. System.out.println(baos.toString());
35.
36. }
37. static class EmptyTrustManager implements X509TrustManager{
38.
39. @Override
40. public void checkClientTrusted(X509Certificate[] chain, String arg1) throws
CertificateException {
42. System.out.println("checkClientTrusted");
43. for(X509Certificate certificate : chain){
44. System.out.println(chain.toString());
45. }
46. System.out.println("arg1="+arg1);
47. }
48.
49. @Override
50. public void checkServerTrusted(X509Certificate[] chain, String arg1) throws
51. CertificateException {
52. System.out.println("checkServerTrusted");
53. for(X509Certificate certificate : chain){
54. System.out.println(chain.toString());
55. }
56. System.out.println("arg1="+arg1);
57. }
58.
59. @Override
60. public X509Certificate[] getAcceptedIssuers() {
61. System.out.println("getAcceptedIssuers");
62. return null;
63. }
64. }
65. }
~~~
3. Android中https請求
下面我們演示如何使用一個網站的證書,跟其進行https通信。
HTTPS測試 測試地址:https://certs.cac.washington.edu/CAtest/
測試證書:http://www.washington.edu/computing/media/load-der.crt
~~~
1. package com.example.https;
2.
3. import java.io.ByteArrayOutputStream;
4. import java.io.IOException;
5. import java.io.InputStream;
6. import java.net.MalformedURLException;
7. import java.net.URL;
8. import java.security.KeyManagementException;
9. import java.security.KeyStore;
10. import java.security.KeyStoreException;
11. import java.security.NoSuchAlgorithmException;
12. import java.security.cert.Certificate;
13. import java.security.cert.CertificateException;
14. import java.security.cert.CertificateFactory;
15. import java.security.cert.X509Certificate;
16.
17. import javax.net.ssl.HttpsURLConnection;
18. import javax.net.ssl.SSLContext;
19. import javax.net.ssl.TrustManager;
20. import javax.net.ssl.TrustManagerFactory;
21. import javax.net.ssl.X509TrustManager;
22.
23. import android.R.integer;
24. import android.app.Activity;
25. import android.os.Bundle;
26. import android.view.Menu;
27. import android.view.MenuItem;
28. import android.view.View;
29.
30. public class MainActivity extends Activity {
31.
32. @Override
33. protected void onCreate(Bundle savedInstanceState) {
34. super.onCreate(savedInstanceState);
35. setContentView(R.layout.activity_main);
36. }
37.
38. public void start(View view){
39. new Thread(new Runnable() {
40.
41. @Override
42. public void run() {
43.
44. try {
45. CertificateFactory certificateFactory =
46. CertificateFactory.getInstance("X.509");
47.
48. InputStream iStream = getAssets().open("load-der.crt");
49.
50. Certificate ca = certificateFactory.generateCertificate(iStream);
51.
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
53.
54. keyStore.load(null, null);
55.
56. keyStore.setCertificateEntry("ca", ca);
57.
58. TrustManagerFactory trustManagerFactory =
59. TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
60. trustManagerFactory.init(keyStore);
61. SSLContext sslContext = SSLContext.getInstance("TLS");
62. sslContext.init(null, trustManagerFactory.getTrustManagers(), null);
63. URL url = new URL("https://certs.cac.washington.edu/CAtest/");
64. HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
65. HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
66.
67. InputStream is = connection.getInputStream();
68. ByteArrayOutputStream baos = new ByteArrayOutputStream();
69. int len;
70. byte[] buffer = new byte[1024];
71. while((len=is.read(buffer))!=-1){
72. baos.write(buffer, 0, len);
73. }
74. System.out.println(baos.toString());
75.
76. } catch (NoSuchAlgorithmException e) {
77. e.printStackTrace();
78. } catch (KeyManagementException e) {
79. e.printStackTrace();
80. } catch (MalformedURLException e) {
81. e.printStackTrace();
82. } catch (IOException e) {
83. e.printStackTrace();
84. } catch (CertificateException e) {
85. e.printStackTrace();
86. } catch (KeyStoreException e) {
87. e.printStackTrace();
88. }
89. }
90. }).start();
91. }
92.
93. }
~~~