1. 程式人生 > >android 使用https請求

android 使用https請求

今年年初就已經吵吵著要把大部分的服務端由http轉成https了,但是由於很多公司還是比較懶,而且有的公司可能不想再多掏一些錢去對自己的網址加入CA認證,所以這件事就一直拖下來了,但是隨著使用者資料越來越多暴露在一些不法分子眼前,所以資訊保安越來越被使用者重視,一些金融、貸款公司已經開始使用這種技術了,今天就來講解一下android上面的通過https對伺服器進行請求。

首先先來解答一下疑惑,我們在做測試的時候經常會對https://www.baidu.com或者https://www.github.com進行一個網路工具類的測試,但是不知道大家有沒有注意到,這些網址連結之前全都是https://的,為什麼我們在訪問的時候完全沒有報錯,也能夠正常的訪問呢。ok,其實這兩個大網站已經被CA認證過了,而CA證書已經被android裝置預設支援了,所以這些CA認證的網站可以直接通過HttpUrlConnection進行連線,當然也可以通過HttpsUrlConnection進行連線。

但是除了被CA認證的網址就不能夠正常的連線了,比如我們訪問神奇的網站12306時,在他的註冊頁面其實已經升級成了Https協議的了,而且這個網站的證書是沒有被CA認證過的。我們來分別對比下百度的 和github 還有我們神奇的網站12306的 簽名檔案~~~

見圖:

第一張是百度網站的 證書檔案資訊


這張是github的證書資訊


這張當然就是12306的嘍


大家可以自己開啟電腦瀏覽器,開啟開發者工具(或者F12),然後點選security就能看到這個資訊了,如果對證書感興趣,還可以點選上邊的“view certificate”去檢視證書的資訊

我們通過上面的三個圖,不難分析出baidu 和github使用的是CA的認證的證書,而12306並沒有,12306用的是自己證書

這就導致了12306需要我們特別去寫一下網路請求,而百度和github則不需要。

那我們怎麼去正常的訪問12306呢,這裡我封裝了一個網路請求類,核心程式碼在這裡:

try {
                    URL url = new URL(path);
                    //1.改成s
                    HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
                    //2.SSLContext 初始化
                    SSLContext tls = SSLContext.getInstance("TLS");
                    MyX509TrustManager myX509TrustManager = new MyX509TrustManager(getX509Certificate(context));

                    TrustManager[] trustManagers={myX509TrustManager};
                    tls.init(null,trustManagers,new SecureRandom());
                    //3.ssl工廠
                    SSLSocketFactory factory = tls.getSocketFactory();
                    //4.新增一個主機名稱校驗器
                    conn.setHostnameVerifier(new HostnameVerifier() {
                        @Override
                        public boolean verify(String hostname, SSLSession session) {
                                if (hostname.equals("kyfw.12306.cn")) {
                                return true;
                            }else{
                                return false;
                                }

                        }
                    });
                    conn.setSSLSocketFactory(factory);
                    conn.setRequestMethod("GET");
                    conn.setReadTimeout(5000);
                    conn.setConnectTimeout(5000);
                    conn.connect();
                    InputStream inputStream = conn.getInputStream();

                    StringBuilder sb=new StringBuilder();
                    int flag;
                    byte[] buf=new byte[1024];
                    while((flag=inputStream.read(buf))!=-1){
                        sb.append(new String(buf,0,flag));
                    }
                    String s = sb.toString();
                    //呼叫對方傳入callback完成回撥操作
                    callBack.onSuccess(s);
                } catch (Exception e) {
                    e.printStackTrace();
                    callBack.onFail(e);
                }

主要的思路是:

1.先將我們常用的httpurlconnection變成HttpsConnection

2.初始化我們的SSLContext 這個類是ssl的一個幫助類,能夠幫助我們去驗證我們的證書檔案

這個環節中其實稍微多一些操作,比如獲取SSLContext的例項

SSLContext tls = SSLContext.getInstance("TLS");
還有建立SSLContext的初始化引數,這個MyX509TrustManager是我自己封裝的類
MyX509TrustManager myX509TrustManager = new MyX509TrustManager(getX509Certificate(context));

封裝的類如下

package com.guaju.httpsrequesttest.http;

import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SignatureException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.X509TrustManager;

/**
 * Created by guaju on 2017/11/7.
 */

public class MyX509TrustManager implements X509TrustManager {
    //如果需要對證書進行校驗,需要這裡去實現,如果不實現的話是不安全 
    X509Certificate mX509Certificate;


    public MyX509TrustManager(X509Certificate mX509Certificate) {
        this.mX509Certificate = mX509Certificate;
    }

    @Override
    public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {

    }

    @Override
    public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
       for (X509Certificate certificate:chain){
           //檢查證書是否有效
           certificate.checkValidity();
           try {
               certificate.verify(mX509Certificate.getPublicKey());
           } catch (NoSuchAlgorithmException e) {
               e.printStackTrace();
           } catch (InvalidKeyException e) {
               e.printStackTrace();
           } catch (NoSuchProviderException e) {
               e.printStackTrace();
           } catch (SignatureException e) {
               e.printStackTrace();
           }

       }


    }

    @Override
    public X509Certificate[] getAcceptedIssuers() {
        return new X509Certificate[0];
    }
}

而上個類中傳入的構造方法中的證書檔案

X509Certificate mX509Certificate;

這個證書檔案需要通過我們下載的證書去獲得,12306的證書在官網首頁,而我們如果開發自己的公司的網站的話,後臺應該會給我們一份,我們拿著這個證書放到assets目錄下(或者後臺的伺服器上)就可以轉變成我們自己的簽名了,下午是12306下載證書的地方:


下方是提供的將assets中的證書檔案流轉化成證書的方法,很簡單:

//拿到自己的證書
   X509Certificate getX509Certificate(Context context) throws IOException, CertificateException {
       InputStream in = context.getAssets().open("srca.cer");
       CertificateFactory instance = CertificateFactory.getInstance("X.509");
       X509Certificate certificate = (X509Certificate) instance.generateCertificate(in);
       return certificate;
   }


建立TrustManager陣列,將上方的MyX509TrustManager放進陣列中去
TrustManager[] trustManagers={myX509TrustManager};
然後呼叫SSLContext的初始化方法
tls.init(null,trustManagers,new SecureRandom());
3.上方的sslcontext初始化好之後,我們就可以做SSLSocketFactory的建立了
SSLSocketFactory factory = tls.getSocketFactory();
然後把這個工廠為我們的連線conn設定上
conn.setSSLSocketFactory(factory);
4.新增主機名稱校驗器,記住這裡的主機名稱地址需要檢視我們的證書的配置,不能瞎寫

證書配置如下圖


下方的名稱及上方的常用名稱

conn.setHostnameVerifier(new HostnameVerifier() {
    @Override
public boolean verify(String hostname, SSLSession session) {
            if (hostname.equals("kyfw.12306.cn")) {
            return true;
}else{
            return false;
}

    }
});
這樣的話就可以訪問12306的註冊頁面了。

ok,為了方便大家使用,我已經提交到github了,如果大家覺得不錯,記得star 或者fork哦 ,多謝~~~

相關推薦

Android Https請求詳解

轉至:http://itindex.net/detail/51666-android-https-demo    Android Https詳細請求全方案實現,包括HttpUrlConnection及HttpClient方式實現指定證書及信任所有的實現,不多說了,以下程

Android Https請求詳細demo(經過測試可用)

   @Override    public boolean verify(String arg0, SSLSession arg1) {     return true;    }   });   HttpsURLConnection connection = (HttpsURLConnection) ur

Android Https請求的簡單使用(Volley Https請求的示例)

導語 數字簽名一般會使用RSA演算法,對於RSA演算法的理解,阮一峰也提供兩篇生動的文章來說明: 上篇 下篇 如果看到一大段數學公式就不想往下看的同學,我這裡給個簡化版的: 將兩個大質數相乘十分容易,但是想要對其乘積進行因式分解卻極其困難,文

android https請求

1、將伺服器生成的.cer檔案放在 assets目錄下 2、直接看程式碼(放在工具類,在請求的地方直接呼叫即可)     public  Context context;     public static void  getCA(Context context){   

使用Charles對Android App的https請求進行抓包

http代理 版本 download ios8 app 5.0 圖片 www 是否 本文背景 公司新項目要求抓取目前市面上一些熱門App的數據,經過研究發現很多App的網絡請求都使用https進行數據傳輸,這樣問題就來了,http使用明文傳輸所有請求都能攔截到,而http

Android進階(二)https請求No peer certificate的解決方法.

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

關於安卓7.0及以上的Https請求抓包問題android:networkSecurityConfig

Android 7.0(API 級別 24)及更高版本預設只承認系統CA,所以預設是安全的,不需要配置。如果想要系統承認使用者自己安裝的CA,則修改配置(比如除錯時會需要抓包)。 面向 Android 6.0(API 級別 23)及更低版本應用的預設配置如下所示,這段配置的意思是,承認系

Charles抓web http、https請求,抓Android http、https請求

 為什麼要抓包? 抓包:能幫助我們定位問題,是後端接口出現的問題,還是前段有問題 Windows下http請求 怎麼攔截請求? 選中要攔截的請求,滑鼠右鍵,點選breakpoints,設定斷點,即可攔截請求 下次再請求這個http路徑時,就自動跳出下面內容 怎麼修改請求 修改r

使用fiddler抓取Androidhttps請求

Fiddler下載地址:http://www.telerik.com/fiddler,個人喜歡在官網下載,安裝之後開啟Fiddler,Tools—>Telerik Fiddler Options—>Connections,在這裡設定允許遠端連線,並設定自己的埠號,如下圖所示:

Android 使用Fiddler抓取Https請求

在開發過程中我們一定碰到過需要檢視從伺服器請求下來的資訊是什麼樣的情況,一般使用log就可以檢視,但是有時候當請求下來的資訊特別多的時候則不怎麼好看了;如果是一般的get請求,只要結合谷歌瀏覽器的一個數據格式化外掛也可以看的很happy,但是萬一是post請求呢?特別還是https型別的請求呢?&n

android-Picasso請求https載入網路圖片不能顯示的解決方案

Picasso載入https的圖片載入不出來的解決方案 最近專案中有需求–要顯示https連結的圖片,但是配置好路徑後原生的Picasso死活沒法加載出圖片,最後在網上找到了如下的解決辦法 確認依賴 compile 'com.squareup.ok

Android進階 二 https請求No peer certificate的解決方法

 在做Android客戶端通過https協議訪問12306,並爬取資料時,出現瞭如下錯誤: 其中有一條錯誤提示是 javax.net.ssl.SSLPeerUnverifiedException: No peer certificate的異常。現給出

Charlse抓包獲取Android應用的https請求資料

1、選單欄依次選擇help->SSL Proxying -> install charlse root certification開啟電腦安裝證書介面(此處以windows為例) 依次點選安裝證書 跳轉到證書匯入嚮導,儲存位置選擇當前使用者和本地電腦都可以,

android ksoap2下webservice的 https請求

參考okhttp呼叫https實現自簽名SSL證書: stackoverflow:How to use Ksoap2 on ssl (https) connection - Android 我的專案中使用網路請求庫是webservice方式實現,依賴

Android中進行https請求信任證書問題

前言 在Android開發專案中難免要進行https請求,如果你也遇到這樣的問題,那麼我想這片部落格能對你有些幫助。java.security.cert.CertPathValidatorException: Trust anchor for certification

Android如何構建一個https請求的httpClient

為了安全性的要求,有時候http請求需要通過https來訪問,那麼在Android上如何實現一個https的httpClient呢 實現方式如下: public static HttpClient getNewHttpClient() {

android 使用https請求

今年年初就已經吵吵著要把大部分的服務端由http轉成https了,但是由於很多公司還是比較懶,而且有的公司可能不想再多掏一些錢去對自己的網址加入CA認證,所以這件事就一直拖下來了,但是隨著使用者資料越來越多暴露在一些不法分子眼前,所以資訊保安越來越被使用者重視,一些金融、貸

android使用Charles抓包https請求

按照正常抓http的方式進行抓包,會出現如下情況:https抓包就是需要在電腦端和移動端裝上安全證書。電腦端的安裝:手機端就是需要到手機瀏覽器開啟chls.pro/ssl下載安全證書安裝到手機上,如下所示:再在青花瓷上設定一下SSL Proxying,7.0以下的androi

android HTTPURLConnection解決不能訪問HTTPs請求

詳細分析Android及Java中訪問https請求exception(SSLHandshakeException, SSLPeerUnverifiedException)的原因及解決方法。 1、現象 用Android(或Java)測試程式訪問下面兩個連結。 h

開源庫android-async-http新增https請求方式

這幾天由於專案要求將http轉換成https請求,要求不做證書驗證。而我使用的是loopj的開源庫android-async-http來完成伺服器請求,但是此庫並未有相關https的示例,故自己動手豐衣足食。經過一番摸索,現記錄如下:封裝了一個httpclient幫助類,以