1. 程式人生 > >Android端關於HTTPS的認證---->可用

Android端關於HTTPS的認證---->可用

1.關於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之間)。

2.普通的HTTP post請求

public void requestPost
(Map<String , String> params){ HttpURLConnection httpURLConnection = null; String result = null; try { //合成引數 byte [] requestParams = generateParams(params); URL url = new URL(requestUrl); httpURLConnection = (HttpURLConnection) url.openConnection(); httpURLConnection.setConnectTimeout(60
*1000); httpURLConnection.setReadTimeout(60*1000); httpURLConnection.setDoOutput(true); httpURLConnection.setDoInput(true); httpURLConnection.setUseCaches(false); httpURLConnection.setRequestMethod("POST"); httpURLConnection.setInstanceFollowRedirects(true); httpURLConnection.connect(); DataOutputStream dos = new
DataOutputStream(httpURLConnection.getOutputStream()); dos.write(requestParams); dos.flush(); dos.close(); if (httpURLConnection.getResponseCode() == HttpURLConnection.HTTP_OK){ result = stream2string(httpURLConnection.getInputStream()); }else { Log.e(TAG, "requestPost: 請求失敗--->"+httpURLConnection.getResponseCode()); } httpURLConnection.disconnect(); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }
當請求的介面地址變為HTTPS型別的話,會丟擲如下異常

12-17 14:08:38.590 18126-18188/? W/System.err: javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
12-17 14:08:38.590 18126-18188/? W/System.err:     at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:357)
12-17 14:08:38.590 18126-18188/? W/System.err:     at com.android.okhttp.internal.http.SocketConnector.connectTls(SocketConnector.java:212)
12-17 14:08:38.590 18126-18188/? W/System.err:     at com.android.okhttp.Connection.connect(Connection.java:1322)
12-17 14:08:38.590 18126-18188/? W/System.err:     at com.android.okhttp.Connection.connectAndSetOwner(Connection.java:1410)
12-17 14:08:38.590 18126-18188/? W/System.err:     at com.android.okhttp.OkHttpClient$1.connectAndSetOwner(OkHttpClient.java:131)
12-17 14:08:38.590 18126-18188/? W/System.err:     at com.android.okhttp.internal.http.HttpEngine.nextConnection(HttpEngine.java:484)
12-17 14:08:38.590 18126-18188/? W/System.err:     at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:465)
12-17 14:08:38.590 18126-18188/? W/System.err:     at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:371)
12-17 14:08:38.590 18126-18188/? W/System.err:     at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:476)
12-17 14:08:38.590 18126-18188/? W/System.err:     at com.android.okhttp.internal.huc.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:118)
12-17 14:08:38.590 18126-18188/? W/System.err:     at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.connect(DelegatingHttpsURLConnection.java:89)
12-17 14:08:38.590 18126-18188/? W/System.err:     at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:25)
12-17 14:08:38.590 18126-18188/? W/System.err:     at com.binguokeji.sdk.library.SimpleNetHelper.post(***.java:232)
12-17 14:08:38.590 18126-18188/? W/System.err:     at com.binguokeji.sdk.library.Workflow$1.run(***.java:42)
12-17 14:08:38.590 18126-18188/? W/System.err:     at java.lang.Thread.run(Thread.java:818)
12-17 14:08:38.590 18126-18188/? W/System.err: Caused by: java.security.cert.CertificateException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
12-17 14:08:38.590 18126-18188/? W/System.err:     at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:324)
12-17 14:08:38.590 18126-18188/? W/System.err:     at com.android.org.conscrypt.TrustManagerImpl.checkServerTrusted(TrustManagerImpl.java:225)
12-17 14:08:38.590 18126-18188/? W/System.err:     at com.android.org.conscrypt.Platform.checkServerTrusted(Platform.java:115)
12-17 14:08:38.590 18126-18188/? W/System.err:     at com.android.org.conscrypt.OpenSSLSocketImpl.verifyCertificateChain(OpenSSLSocketImpl.java:643)
12-17 14:08:38.590 18126-18188/? W/System.err:     at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method)
12-17 14:08:38.590 18126-18188/? W/System.err:     at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:353)
12-17 14:08:38.590 18126-18188/? W/System.err:     ... 14 more
12-17 14:08:38.590 18126-18188/? W/System.err: Caused by: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
12-17 14:08:38.590 18126-18188/? W/System.err:     ... 20 more

有道上翻譯的錯誤資訊為----->沒有找到認證路徑的信任錨。   就是因為HTTPS請求有一層ssl加密協議,沒有認證的話是不能隨意訪問的

3.為HTTPS請求設定信任證書

public void setCertificates(HttpsURLConnection httpsURLConnection , InputStream... certificates) {
    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) {

            }
        }
        SSLContext sslContext = SSLContext.getInstance("TLS");
TrustManagerFactory trustManagerFactory =
                TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keyStore);
sslContext.init(null, trustManagerFactory.getTrustManagers(), new SecureRandom());
httpsURLConnection.setSSLSocketFactory(sslContext.getSocketFactory());
} catch (Exception e) {
        e.printStackTrace();
}

}
在上邊post請求的時候做一下判斷
URL url = new URL(requestUrl);
if (url.getProtocol().toUpperCase().equals("HTTPS")){
    httpsURLConnection = (HttpsURLConnection) url.openConnection();
setCertificates(httpsURLConnection , new ByteArrayInputStream("信任證書的key".getBytes("UTF-8"));
httpURLConnection = httpsURLConnection;
}
httpURLConnection = (HttpURLConnection) url.openConnection();
這樣就可以實現HTTPS型別地址的訪問了