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 通信简单图示:
![](https://box.kancloud.cn/c4059711176b612620a1e86abb870e0c_597x357.jpg)
SSL 通信详细图示:
![](https://box.kancloud.cn/b3335983866e61fd3a0987ccd0bcb704_641x482.jpg)
当请求使用自签名证书的网站数据时,例如请求 12306 的客运服务页面:https://kyfw.12306.cn/otn/,
则会报下面的错误,原因是客户端的根认证机构不能识别该证书。
![](https://box.kancloud.cn/6a988cfe688b1ca605ee7bd9755f3656_1122x525.jpg)
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. }
~~~