1. 程式人生 > >Android 偶遇HTTPS

Android 偶遇HTTPS

ace reat 目錄 服務 api 密鑰對 ref 簡便 本地

HTTPS ,該來的總要來的。
最近領導對移動端開發提出了很多優化的要求啊!其中一點就是數據安全性,之前安卓後端接口一直是用的HTTP,那麽我想了想,HTTPS應該是入門級的了,趕緊找資料整理了下!
對於向權威機構申請過證書的網絡地址,用OkHttp或者HttpsURLConnection都可以直接訪問,不需要做額外的事情。但是申請證書要$$的,所以開發的時候我們接口經常是使用自簽名證書,或者即使上線了也還是用自簽名的,因為安卓用到的基本都是數據接口,又不會用瀏覽器訪問,不想付錢不行咩!

訪問自簽名網址
使用keytool生成證書
keytool是JDK提供的管理加密密鑰、X.509證書鏈和可信證書密鑰庫的簡便工具。安卓開發必定安裝了JDK並且一般都會配置好環境變量,所以你可以直接在終端或DOC窗口輸入keytool命令來查看幫助。

1.生成密鑰對

1
keytool -genkey -alias server -keyalg RSA -keystore server.jks
-alias後面跟的是唯一別名,-keystore後面填保存秘鑰對的文件路徑
還可以添加一個-validity 天數聲明有效期

需要註意的地方:執行命令之後第一個問題讓你輸入名字的地方最好設置成域名,比如這樣baidu.com或者這樣localhost,反正匹配你要調式的域名就對了,當然,如果你在安卓上調試,那麽本地地址可能用不了。

2.導出證書

上面生成了服務端使用的密鑰對,現在可以通過它生成證書給客戶端使用

1
keytool -export -alias server -storepass 123456 -keystore server.jks -file server.cer

-storepass後面跟的是你剛才設置的密碼,不加這個也沒關系,它會主動問你!;-file設置了保存證書的路徑

服務端配置
這裏我使用tomcat8進行測試,它的配置很簡單,修改tomcat目錄下的conf/server.xml文件,添加如下內容,這裏設置了端口號為8443

<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="150" SSLEnabled="true" scheme="https" secure="true"

clientAuth="false" sslProtocol="TLS"
keystoreFile="密鑰庫文件路徑,也就是.jks文件"
keystorePass="密碼" />
安卓端配置
加載證書
把之前生成的證書(.cer)放到安卓項目的assets或者raw目錄下,讀取文件流用以下方法獲取SSLSocketFactory 。

public static SSLSocketFactory getSslSocketFactory(InputStream certificates)
{
SSLContext sslContext = null;
try
{
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");

        Certificate ca;
        try {
            ca = certificateFactory.generateCertificate(certificates);

        } finally {
            certificates.close();
        }

        // Create a KeyStore containing our trusted CAs
        String keyStoreType = KeyStore.getDefaultType();
        KeyStore keyStore = KeyStore.getInstance(keyStoreType);
        keyStore.load(null, null);
        keyStore.setCertificateEntry("ca", ca);

        // Create a TrustManager that trusts the CAs in our KeyStore
        String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
        tmf.init(keyStore);

        // Create an SSLContext that uses our TrustManager
        sslContext = SSLContext.getInstance("TLS");
        sslContext.init(null, tmf.getTrustManagers(), null);

    } catch (Exception e)
    {
        e.printStackTrace();
    }

    return sslContext != null? sslContext.getSocketFactory():null;
}

OkHttp
在OkHttp中使用很簡單,獲取SSLSocketFactory之後通過OkHttp的構建方法傳入就行了。
使用的OkHttp版本是3.2.0。

OkHttpClient client = new OkHttpClient.Builder()
.sslSocketFactory(sslSocketFactory)
.build();
設置完之後你就可以訪問該證書對應的域名地址了,不需要別的附加操作了。

HttpsURLConnection
OkHttp的API與安卓中默認提供的URLConnection是很接近的,所以配置也是如出一轍。

URL url = new URL("https://....");

HttpsURLConnection httpsURLConnection = (HttpsURLConnection) url.openConnection();

httpsURLConnection.setSSLSocketFactory(sslSocketFactory);
雙向驗證
雙向認證需要兩個密鑰實體,一個放服務端一個放客戶端。
前面我們已經實現單向的認證,現在只需要給客戶端生成一個密鑰庫,並且讓服務端信任客戶端就可以了。

生成客戶端密鑰

keytool -genkey -alias android -keyalg RSA -keystore android.jks
導出客戶端證書(字符串形式)

keytool -keystore android.jks -alias android -exportcert -rfc > android.pem
將導出的證書添加信任到服務端的密鑰庫

keytool -importcert -trustcacerts -alias android -keystore server.jks -file android.pem
服務端配置
修改tomcat目錄下的conf/server.xml文件

<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
sslProtocol="TLS"
keystoreFile="密鑰庫文件路徑,也就是.jks文件"
keystorePass="密碼"
//修改兩條內容,其它和之前單向認證一樣就行
clientAuth="true"
truststoreFile="和keystoreFile填一樣" />

Android 偶遇HTTPS