1. 程式人生 > >android https訪問

android https訪問

https的握手過程

https在傳輸真正的資料之前,需要客戶端和服務端進行一次協議握手,主要配置好兩邊的私鑰和一些初始化工作,大致流程如下圖:

這裡寫圖片描述

使用中遇到的問題

最近專案需要使用https方式訪問,專案是用retrofit+okhttp框架,需要把以前的http全部改為https訪問;關於https訪問配置的方式有三種

  • 信任所有證書
  • 驗證某一個特定證書

信任所有證書

直接將以前的http改成https即可,不需要做任何改變,照理說第一種改變https即可,但是我卻出現這種異常

Suppressed: javax.net.ssl.SSLHandshakeException: Handshake failed
04
-17 18:09:07.892 3160-3160/com.chinamobile.iot.easiercharger W/System.err: ... 36 more 04-17 18:09:07.892 3160-3160/com.chinamobile.iot.easiercharger W/System.err: Caused by: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x9e23da80: Failure in SSL library, usually a protocol error 04-17 18:09:07.892
3160-3160/com.chinamobile.iot.easiercharger W/System.err: error:100bd10c:SSL routines:ssl3_get_record:WRONG_VERSION_NUMBER (external/boringssl/src/ssl/s3_pkt.c:311 0xa92997f7:0x00000000) 04-17 18:09:07.902 3160-3160/com.chinamobile.iot.easiercharger W/System.err: at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method)
04-17 18:09:07.902 3160-3160/com.chinamobile.iot.easiercharger W/System.err: at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:353) 04-17 18:09:07.902 3160-3160/com.chinamobile.iot.easiercharger W/System.err: ... 35 more 04-17 18:09:07.902 3160-3160/com.chinamobile.iot.easiercharger W/System.err: Caused by: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x9e23da80: Failure in SSL library, usually a protocol error 04-17 18:09:07.902 3160-3160/com.chinamobile.iot.easiercharger W/System.err: error:100bd10c:SSL routines:ssl3_get_record:WRONG_VERSION_NUMBER (external/boringssl/src/ssl/s3_pkt.c:311 0xa92997f7:0x00000000) 04-17 18:09:07.902 3160-3160/com.chinamobile.iot.easiercharger W/System.err: at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method) 04-17 18:09:07.902 3160-3160/com.chinamobile.iot.easiercharger W/System.err: at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:353) 04-17 18:09:07.902 3160-3160/com.chinamobile.iot.easiercharger W/System.err: ... 35 more

這種問題原因有多重,可能證書有問題,也可能是自己的程式碼有問題;我的專案出現這個問題的原因是:

未改變https之前,我的網路介面類似於這種

http://www.power.com:80

改成https後是這種

https://www.power.com:80

改了之後就出現上訴的錯誤,你們能看出問題所在嗎?

那就是埠號

http協議預設使用的埠號是80,https預設的埠是443,而這裡我改動https後端口號沒變,所以這個域名是訪問不通的,除非https通訊埠號被改成了80才會通,解決辦法就是埠號改成443即可解決

這是我使用第一種方式引發的問題,如果使用自簽名的證書或者忽略所有證書,一旦你的埠號有誤,也可能出現上訴問題,夥伴們,擦亮眼睛吧!

信任某一特定證書

獲取證書

可以從網站上匯出證書,具體方法可點選參考,匯出比較簡單,重要的是格式,博主在匯出的.cer格式的證書後,反正asstes目錄下,最後以stream方式開啟,但是在okhttp使用這個證書檔案驗證時總出錯,報錯資訊大致是code編碼問題,思考了良久和查詢了資料,最後確定原因是證書用在okhttp框架裡去的時候要永城utf-8格式,以下是解決方案:

  1. 將cer檔案裡面的key原封不等的拷貝出來
public final static String SSL_KEY = "-----BEGIN CERTIFICATE-----\n" +
            "Fw0xODAxMTYwMDAwMDBaFw0yMDAyMTUxMjAwMDBaMIGdMQswCQYDVQQGEwJDTjEQ\n" +
            "MA4GA1UEBxMHQ2hlbmdkdTE4MDYGA1UEChMvQ2hpbmEgTW9iaWxlIElPVCBDb21w\n" +
            "YW55IExpbWl0ZWQgQ2hlbmdkdSBicmFuY2gxJjAkBgNVBAsTHUluZm9ybWF0aW9u\n" +
            "IFRlY2hub2xvZ3kgQ2VudGVyMRowGAYDVQQDExF3d3cudGF4aWFpZGVzLmNvbTCC\n" +
            "ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOryUl/OGkrUkqSzoimarOPv\n" +
            "V0qQ7EsyS1ny0UZ7jcxnFS7ztOLh/0XIaPvX4e2KWgdcgxL8LbQ/gFKeRr5s6Uub\n" +
            "QUeczE9+CO4ic5opzS76QVJVH0kTSBoB1HBJ0TAV3XhSt+SOF7T5bpJrcCdijw7X\n" +
            "-----END CERTIFICATE-----";
  1. 匯入時要進行一次utf編碼
InputStream[] key = new InputStream[]{new Buffer().writeUtf8(SSL_KEY_TEST).inputStream()};
  1. 進行證書驗證
public static SSLParams setCertificates(InputStream... certificates)
    {
        SSLParams sslParams = new SSLParams();
        try
        {
            CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
            KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
            keyStore.load(null);
            int index = 0;
            for (InputStream certificate : certificates)
            {
                String certificateAlias = Integer.toString(index++);
                keyStore.setCertificateEntry(certificateAlias, certificateFactory.generateCertificate(certificate));

                try
                {
                    if (certificate != null){
                        certificate.close();
                    }
                } catch (IOException e)
                {
                    e.printStackTrace();
                }
            }
            SSLContext sslContext = SSLContext.getInstance("TLS");

            TrustManagerFactory trustManagerFactory =
                    TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());

            trustManagerFactory.init(keyStore);
            sslContext.init
                    (
                            null,
                            trustManagerFactory.getTrustManagers(),
                            new SecureRandom()
                    );

            sslParams.trustManager = (X509TrustManager) trustManagerFactory.getTrustManagers()[0];
            sslParams.sSLSocketFactory = sslContext.getSocketFactory();
            return sslParams;
        } catch (Exception e)
        {
            e.printStackTrace();
        }
        return sslParams;
    }

成功後,可以去換一個錯誤的證書測試一下,不要嘗試著去修改正確證書裡面的內容,這樣會造成第三步驟裡面證書驗證丟擲異常,導致所有證書這塊程式碼都沒執行,信任所有證書;建議去其他https網站,按照上面步驟匯出一個第三方的cer證書,最後用錯誤的證書測試會有以下幾個字眼,就表示成功;

 Trust anchor for certification path not found.

服務端驗證

以上講述的都是客戶端驗證服務端的證書,客戶端只包含了服務端的公鑰;而雙向驗證則會多了幾點,詳細請看下:

  1. 客戶端傳送自己的SSL版本資訊、支援加密演算法等資訊
  2. 服務端收到後傳送SSL版本資訊、支援加密演算法等資訊,並且傳送自己的公鑰證書給客戶端
  3. 客戶端會驗證公鑰證書的合法性,CA機構頒佈、過期或者是否信任
  4. 如果不通過將會終止
  5. 服務端會要求客戶端傳送客戶端自己的公鑰證書給服務端,收到後,服務端會對其證書進行驗證
  6. 驗證通過後,會獲得客戶端的公鑰;至此,客戶端有自己的私鑰和服務端的公鑰;服務端有自己的私鑰和客戶端的公鑰
  7. 客戶端會發送自己所支援的對稱加密方案,服務端會選擇一個加密程度最高的演算法
  8. 選擇後,會用客戶端的公鑰加密選擇的方案,加密後傳送給客戶端
  9. 客戶端用自己的私鑰進行解密,並使用該加密方案產生初始的加密祕鑰
  10. 客戶端使用服務端的公鑰加密該對稱私鑰,傳送給服務端
  11. 服務端收到加密對稱私鑰後,用自己的私鑰解密後會獲得對稱祕鑰,
  12. 最後,兩邊都獲得了對稱祕鑰,使用該祕鑰進行通訊
    單向認證沒有服務端對客戶端的證書驗證,並且在第8步驟是明文傳送加密方案

程式碼完成

	//客戶端祕鑰keystore
    KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); 
    //讀取客戶端私鑰
    InputStream ksIn = context.getAssets().open(CLIENT_PRI_KEY);
    //keystore載入祕鑰和密碼
    keyStore.load(ksIn, CLIENT_BKS_PASSWORD.toCharArray());
    ksIn.close();
    //初始化SSLContext
    SSLContext sslContext = SSLContext.getInstance(“TLS”);
    KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("X.509");
    
    keyManagerFactory.init(keyStore, CLIENT_BKS_PASSWORD.toCharArray());
    //第一個引數向服務端發起驗證 第二個用於驗證服務端的證書
    sslContext.init(keyManagerFactory.getKeyManagers(), null, null); 
 
    sslSocketFactory = sslContext.getSocketFactory();

總結

證書驗證

  • 獲取證書管理類CertificateFactory和KeyStore
  • 使用證書管理類CertificateFactory和證書初始化Keystore
  • 獲取證書信任管理類TrustManagerFactory,將Keystore裡面的證書新增到證書信任管理類中
  • SSL上下文類SSLContext用證書信任管理類進行初始化
  • 將SSL新增到okhttpbuilder裡面即可

相關推薦

android https訪問

https的握手過程 https在傳輸真正的資料之前,需要客戶端和服務端進行一次協議握手,主要配置好兩邊的私鑰和一些初始化工作,大致流程如下圖: 使用中遇到的問題 最近專案需要使用https方式訪問,專案是用retrofit+okhttp框架,需要把以前的ht

AndroidHttps 訪問

Https 介面使用環境,伺服器端一個證書,生成一個客戶端證書,在訪問服務介面時使用客戶端證書,訪問伺服器端https,增強對傳輸安全。 在開發過程中使用okhttp框架來實現https訪問自簽名的介面。首先拿到後臺自簽名證書sChat.cer 放在assets裡面。通過getAsset

android ksoap2 訪問https javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorExce

android 使用ksoap2 訪問webservice時,若訪問的是https,報https javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException 解決方案:

Android網路訪問之http、https、 cookie的使用

最近公司做一個遊戲SDK,只有我一個人做~~~~~~~~,以前也沒做過這個,起初感覺無從下手,前前後後花了大概4周的時間,與第一家廠家對接完成的時候,總算鬆了口氣。專案中的網路模組,從http開始調通,然後加上cookie,最後換成https,感覺顯目的大半時間都花在這

Android開發框架xUtils3.x新手教學(二)HTTPS訪問

現在越來越多的專案採用Https安全通訊,今天來介紹一下xUtils裡如何使用Https。 一、弄一個SSL證書(.crt檔案),放到專案assets目錄下。 二、建立HttpUtils類,程式碼如下: import javax.net.ssl.HttpsURLConne

Nginx實現ssl一級、二級域名證書部署並用https訪問代理轉發服務器

www. log 所有 null rec write include cal direct 1. 規劃 域名 解析IP Nginx代理 htpps://www.devcult.com 47.88.10.155 htpps://auto.devcult.c

Apache環境修改.htaccess文件實現子目錄強制HTTPS訪問

地址 自己 一起 文件中 目錄 int 們的 如何 ret 如果要在Apache環境下實現子目錄強制HTTPS地址訪問,該怎麽實現呢?在此文章中將與大家一起分享如何在Apache環境下修改.htaccess文件來實現子目錄強制HTTPS地址訪問。 1、根目錄域名。甚至比較簡

第7章 Android訪問網絡資源

資源 async 圖片 pcl src sync tro client span https://developer.android.google.cn/studio/index.html 範例 7-6(HttpClient與AsyncTask結合下載圖片)

Centos7.2下Nginx配置SSL支持https訪問(站點是基於.Net Core2.0開發的WebApi)

ack 保存 受害者 etc proxy cer 查看 綁定 客戶端 準備工作 1.基於nginx部署好的站點(本文站點是基於.Net Core2.0開發的WebApi,有興趣的同學可以跳http://www.cnblogs.com/GreedyL/p/7422796.ht

Nginx 實現Https訪問

https nginx 默認情況下ssl模塊並未被安裝,如果要使用該模塊則需要在編譯時指定–with-http_ssl_module參數,安裝模塊依賴於OpenSSL庫和一些引用文件,通常這些文件並不在同一個軟件包中。通常這個文件名類似libssl-dev1. 生成證書1.1創建服務器私鑰mkdi

nginx強制使用https訪問(http跳轉到https

nginx強制使用https訪問(htt 需求簡介基於nginx搭建了一個https訪問的虛擬主機,監聽的域名是test.com,但是很多用戶不清楚https和http的區別,會很容易敲成http://test.com,這時會報出404錯誤,所以我需要做基於test.com域名的http向https的強制跳

certbot在Centos7上配置合法簽名證書,實現nginx的https訪問

certbot合法簽名證書 nginx配置https 咖菲貓-李常明筆記 公司因之前使用的openssh創建的自簽名證書,有一個弊端,就是在某些客戶端上不能使用此證書,無法使用https連接,所以,研究了一下certbot 做簽名證書! certbot的官網地址: https://certbot.

IIS7實現訪問HTTP定向至HTTPS訪問

style pos img str ref load 功能 window 模式 工具及軟件: 系統:windows2008R2 軟件:IIS7.0,IIS的Microsoft URL重寫模塊2.0 下載 操作步驟: 1、下載並在IIS中安裝Microso

https----------如何在phpstudy環境下配置apache的https訪問以及訪問http自動跳轉成https

寫入 rom virtual write rule 找到 engine rul str 1、首先在 httpd.conf裏面修改幾個地方   找到 #LoadModule ssl_module modules/mod_ssl.so 去掉前面的#   Include conf

快速安裝Tomcat 並實現HTTPS訪問

SSL Tomcat HTTPS HTTPS,在HTTP下加了一層SSL,用於安全的HTTP數據傳輸,對於數據敏感的網址必須要使用HTTPS協議,本文將介紹如何快速安裝Tomcat,並實現HTTPS訪問。 安裝Tomcat 安裝tomcat必須得有java環境,所以先安裝JDK; 1、安裝JDK

Apache配置實現https訪問

yum安裝Apache實現https訪 編譯安裝Apache實現https訪問 Apache實現https過程 Apache配置實現https訪問一、編譯安裝的Apache配置https訪問1、軟件環境HTTPS是以安全為目標的HTTP通道,簡單講是HTTP的安全版。谷歌已經制定了一項長遠的計劃,

NatApp開啟HTTPS訪問方式

eight http 分享圖片 bubuko ima src 免費 服務 tps 一、首先需要到付費隧道中選擇免費開啟https 二、其次需要重新啟動natapp服務,如下圖出現兩個隧道說明OK NatApp開啟HTTPS訪問方式

nginx配置https訪問

添加 方式 客戶端瀏覽器 配置 匹配 能夠 編譯安裝 mail 們的 nginx配置https訪問一、https簡介HTTPS其實是有兩部分組成:HTTP + SSL/TLS,也就是在HTTP上又加了一層處理加密信息的模塊。服務端和客戶端的信息傳輸都會通過TLS進行加密,所

cas導入證書使用https訪問

提示 timeout col and conn 成功 conf core 安裝 1、生成服務器端秘鑰庫 2、在Tomcat中導入該秘鑰庫 2.1 修改server.xml配置文件 3、將cas-server.war包部署到tomcat中 4、在瀏覽器裏實驗ca

Docker以https訪問Harbor私有倉庫(二)

bubuko 新建 code row mage alt mac 1.2 登錄 1 說明 前文Centos7搭建Harbor私有倉庫(二)中,我們以https方式搭建了Harbor,本篇我們主要配置Docker以https方式訪問Harbor私有倉庫 2 Docker配置