[セットトップ]AndroidのHttpsの使い方


AndroidはどのようにHttpsを使いますか?
技術交流1群:46523908技術交流2群:46505645 NoHttpソースコード及びDemo:https://github.com/Y0LANDA/NoHttp
NoHttpはAndroidネットワークのリクエストとダウンロードを専門とするフレームワークです.
この文章はNoHttpシリーズの中で重要なもので、内容を紹介します.
Httpsとは?
HTTPS(フルネーム:Hyper Text Transfer Protocol over Secure Socket Layer)は、セキュリティを目指すHTTPチャネルであり、簡単に言えばHTTPのセキュリティ版である.すなわち,HTTPの下にSSL層を加えると,HTTPSのセキュリティ基盤はSSLであるため,暗号化の詳細はSSLが必要となる.これはURI Scheme(抽象識別子体系)であり、文法類はHttp:体系と同じである.安全なHTTPデータ転送に使用します.Https:URLはHTTPを使用していることを示していますが、HTTPSにはHTTPとは異なるデフォルトポートと暗号化/認証層(HTTPとTCPの間)があります.このシステムの最初の開発は、NetScape社が行い、ブラウザNetscape Navigatorに内蔵し、認証と暗号化の通信方法を提供した.現在、金融、ネット通販など、支払いに関する分野など、万維のネット上の安全で敏感な通信に広く使われています.今回は無理をしないで、私たちは深く浅く出て、まず最も原始的なHttpsを言って、それからフレームワークはどのようにフレームワークはどのように1つの言葉はHttpsを使います
Androidは原始JavaコードでどのようにHttpsを使います
まずAndroidがどのように最も原始的なjavaコードでネットを要求するかを普及させて、大神はかすめてください.AndroidはJavaで開発され、Javaが持参したhttp APIはHttpURLConnection、AndroidシステムはApache Httpclientに加え、その後HttpClientはSDKでGoogleに削除されたので、HttpClientを使ってネットリクエストをすることもお勧めしませんので、ここでもHttpURLConnectionをリストする方法しかありません.
ステップ1:アドレスの接続を開く
ここで私のブログのアドレスを開けて、GET方法でお願いします.
URL url = new URL("http://blog.csdn.net/yanzhenjie1003");
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");

ステップ2:Https要求と判断し、SSLSocketFactoryを設定する
Httpsリクエストであれば、セキュリティチェックなどの操作を行い、ここではSSLSokcetFactoryを設定します.ここでは2つの方法があります.1つはHttps証明書を含んでいるもので、1つは証明書がなくて直接Httpsリクエストを許可しているもので、証明書が証明書でないのはSSLContextから来ています.
//   SSLSocketFoactory,     :1.       2.       ;      
if (urlConnection instanceof HttpsURLConnection) { //  Https  
    SSLContext sslContext = SSLContextUtil.getSSLContext();
    if (sslContext != null) {
        SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
        ((HttpsURLConnection) urlConnection).setSSLSocketFactory(sslSocketFactory);
    }
}

では、SSLContextはどのように生成されますか.ハハ、急いでいません.まず、この要求の流れを終えて、証明書のロードを後ろに見てみましょう.
ステップ3:必須プロパティの設定
//     
urlConnection.setConnectTimeout(8 * 1000);
urlConnection.setReadTimeout(8 * 1000);

ステップ4:データを読み込み、メインスレッドに送信し、接続を解除
int responseCode = urlConnection.getResponseCode();
if (responseCode == 200) { //     
    InputStream inputStream = urlConnection.getInputStream();
    //     ,      
    ...
    inputStream.close();
}
urlConnection.disconnect();

完全なコード
URL url = new URL("http://blog.csdn.net/yanzhenjie1003");
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");

//   SSLSocketFoactory,     :1.       2.       ;      
if (urlConnection instanceof HttpsURLConnection) { //  Https  
    SSLContext sslContext = SSLContextUtil.getSSLContext();
    if (sslContext != null) {
        SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
        ((HttpsURLConnection) urlConnection).setSSLSocketFactory(sslSocketFactory);
    }
}

//     
urlConnection.setConnectTimeout(8 * 1000);
urlConnection.setReadTimeout(8 * 1000);

int responseCode = urlConnection.getResponseCode();
if (responseCode == 200) { //     
    InputStream inputStream = urlConnection.getInputStream();
    //     ,      
    ...
    inputStream.close();
}
urlConnection.disconnect();

これでリクエスト全体が完了しますが、Androidリクエストネットワークはこれだけのコードで、それから私たちはもう少し完璧に書いて、それからパラメータをカプセル化して、誤りを許容するなど、小さなフレームワークです.簡単ではないでしょうか.
流行のフレームワークNoHttpを使ってどのようにHttpsを游びますか
NoHttpを使うのはあまり簡単ではありません.パラメータを伝えたり、ファイルを渡したり、ダウンロードしたりするのは、基本的に1、2つの言葉でできます.
Request<String> request = NoHttp.createStringRequest(url, RequestMethod.POST);

//       SSLSokcetFactory       
SSLContext sslContext = SSLContextUtil.getSSLContext();
if (sslContext != null) {
    SSLSocketFactory socketFactory = sslContext.getSocketFactory();
    httpsRequest.setSSLSocketFactory(socketFactory);
    requestQueue.add(0, request, httpListener);//        ,      
}

上にSocketを設定したコードは同じで、残りはnewのリクエストオブジェクトが一言で終わることに気づきました.原生よりも簡単なのではないでしょうか.
このフレームワークはNoHttpと呼ばれ、Androidオープンソースネットワークフレームワークです.ソース管理:https://github.com/Y0LANDA/NoHttpチュートリアルブログ:http://blog.csdn.net/yanzhenjie1003
SSLSocketFactoryオブジェクトはどうやって来ますか?
上は純粋なAndroidコードでもNoHttpフレームワークでもSSLContextを使っていますが、こいつは証明書管理と信頼管理器を担当しています.Httpsは証明書があっても証明書がなくてもいいと言っています.この2つの状況を見てみましょう.
セキュリティ証明書のあるSSLContext
Httpsの証明書をassetsディレクトリの下に置いて、ストリームでロードします.
public static SSLContext getSSLContext() {
    //   SSLContext  
    SSLContext sslContext = SSLContext.getInstance("TLS");
    //  assets     
    InputStream inStream = Application.getInstance().getAssets().open("srca.cer");

    //     
    CertificateFactory cerFactory = CertificateFactory.getInstance("X.509");
    Certificate cer = cerFactory.generateCertificate(inStream);

    //    
    KeyStore kStore = KeyStore.getInstance("PKCS12");
    kStore.load(null, null);
    kStore.setCertificateEntry("trust", cer);//          

    //      
    KeyManagerFactory keyFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
    keyFactory.init(kStore, null);//          

    //      
    TrustManagerFactory tFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tFactory.init(kStore);//            

    //    
    sslContext.init(keyFactory.getKeyManagers(), tFactory.getTrustManagers(), new SecureRandom());
    return sslContext;
}

強調しなければならないのは、最後の文のnew SecureRandom()がAndroid 4.4以前のシステムにバグがありました.  
AndroidシステムのSecureRandomのバグを修復
Android 4.4以前のバージョンのJava暗号化アーキテクチャ(JCA)で使用されていたApache Harmony 6.0 M 3およびそれ以前のバージョンのSecureRandom実装には、classlib/modules/security/src/main/java/common/org/apache/harmony/security/provider/crypto/SHA1PRNG_SecureRandomImpl.javaファイルのengineNextBytes()メソッドにセキュリティ・ホールが存在する.ユーザが乱数を生成するためのシードを提供していない場合、プログラムはオフセット量を正しく調整することができず、疑似乱数生成器(PRNG)が乱数シーケンスを生成するプロセスを予測することができる.Butの喜ぶべきNoHttp内部はすでにfixしているというバグですが、皆さんが自分でフレームワークを書くなら、この問題を修復するために多くのコードを書くかもしれませんので、視聴者の皆さんにNoHttpを使うことをお勧めします.   
セキュリティ証明書のないSSLContext
セキュリティ証明書の生成が必要なSSLContextを見てください.証明書の要求は必要ありません.2つのオブジェクトが必要です.1つはSSLContextです(説明しました).もう1つはHostnameVerifierで、その名の通りホスト名が一致するという意味で、コードを見てみましょう.
public static SSLContext getSLLContext() {
    SSLContext sslContext = null;
    try {
        sslContext = SSLContext.getInstance("TLS");
        sslContext.init(null, new TrustManager[]{new X509TrustManager() {
            @Override
            public void checkClientTrusted(X509Certificate[] chain, String authType)  {}

            @Override
            public void checkServerTrusted(X509Certificate[] chain, String authType) {}

            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return new X509Certificate[0];
            }
        }}, new SecureRandom());
    } catch (Exception e) {
        e.printStackTrace();
    }
    return sslContext;
}

このように簡単に、null証明書マネージャにデフォルトの信頼マネージャを渡すだけでいいです.次にHostnameVerifierを見てみましょう.ホスト名チェックである以上、私たちは直接通過します.
private static HostnameVerifier hostnameVerifier = new HostnameVerifier() {
    @Override
    public boolean verify(String hostname, SSLSession session) {
        return true;
    }
};

これはどう使いますか.Android原生コードの使い方では、SSLContextを取得する方法名が異なり、setHostnameVerifierが増えました.その他はセキュリティ証明書の使用と一致しています.
URL url = new URL("http://blog.csdn.net/yanzhenjie1003");
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");

//   SSLSocketFoactory,     :1.       2.       ;      
if (urlConnection instanceof HttpsURLConnection) { //  Https  
    SSLContext sslContext = SSLContextUtil.getSSLContext();
    if (sslContext != null) {
        SSLSocketFactory sslSocketFactory = sslContext.getSLLContextNoCertificate();
        ((HttpsURLConnection) urlConnection).setSSLSocketFactory(sslSocketFactory);
        ((HttpsURLConnection) urlConnection).setHostnameVerifier(SSLContextUtil.hostnameVerifier);
    }
}

//     
urlConnection.setConnectTimeout(8 * 1000);
urlConnection.setReadTimeout(8 * 1000);

int responseCode = urlConnection.getResponseCode();
if (responseCode == 200) { //     
    InputStream inputStream = urlConnection.getInputStream();
    //     ,      
    ...
    inputStream.close();
}
urlConnection.disconnect();

NoHttpの使い方、コードは上のNoHttpが証明書をロードしたのと同じで、setHostnameVerifierの文が増えました.
Request<String> request = NoHttp.createStringRequest(url, RequestMethod.POST);

SSLContext sslContext = SSLContextUtil.getSSLContext();
if (sslContext != null) {
    SSLSocketFactory socketFactory = sslContext.getSLLContextNoCertificate();
    httpsRequest.setSSLSocketFactory(socketFactory);
    httpsRequest.setHostnameVerifier(SSLContextUtil.hostnameVerifier);
    requestQueue.add(0, request, httpListener);//        ,      
}

全文を通読したら、AndroidのHttpsが使われると信じていますよね?文章の下に伝言はありませんよ.
NoHttpソースコードおよびDemo:https://github.com/Y0LANDA/NoHttp