編輯:關於android開發
NoHttp是專門做Android網絡請求與下載的框架。
這一篇文章是NoHttp系列中比較重要的,為大家介紹一下內容:
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,再說框架怎麼框架怎麼一句話使用Https
先普及一下Android怎麼用最原始java代碼請求網絡,大神請掠過。
Android用Java開發,Java自帶的http API有HttpURLConnection
,Android系統又加上了Apache Httpclient
,加上後來HttpClient
在SDK中被Google刪除,所以我們也不推薦使用HttpClient來做網絡請求了,所以在這裡呢也只給列出HttpURLConnection
的方式。
這裡咱打開我的博客地址,用GET方法請求
URL url = new URL("http://blog.csdn.net/yanzhenjie1003");
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
如果是Https請求,那麼做安全校驗等操作,這裡設置SSLSokcetFactory
,這裡有兩種方法,一種是包涵Https證書的,一種是沒有證書直接允許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
怎麼生成呢,哈哈先不急,咱們先把這個請求的流程走完,證書的加載往後邊看哦。
// 設置屬性
urlConnection.setConnectTimeout(8 * 1000);
urlConnection.setReadTimeout(8 * 1000);
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不要太簡單,什麼傳參數、傳文件、下載之類的,基本都是一兩句話就搞定。
Request 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開源網絡框架。
上面不論是純Android代碼還是NoHttp框架都用到了SSLContext
,這家伙呢就是負責證書管理和信任管理器的,我們說Https可以有證書也可以沒有證書,我們來看這兩種情況。
我們把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()
在Android4.4之前的系統中有Bug。
Android 4.4之前版本的Java加密架構(JCA)中使用的Apache Harmony 6.0M3及其之前版本的SecureRandom實現存在安全漏洞,具體位於classlib/modules/security/src/main/java/common/org/apache/harmony/security/provider/crypto/SHA1PRNG_SecureRandomImpl.java
文件的engineNextBytes()
方法裡。當用戶沒有提供用於產生隨機數的種子時,程序不能正確調整偏移量,導致偽隨機數生成器(PRNG)生成隨機序列的過程可被預測。
But值得高興的NoHttp內部已經fix了這一bug,如果大家要自己寫框架,恐怕要寫很多代碼去修復這個問題啦,所以推薦各位看官還是使用NoHttp。
上面看到需要需要安全證書的生成SSLContext就可以了,然後不需要證書的請求,需要兩個對象,一個是SSLContext
(上面已經解釋過了);另一個是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 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中Action Bar的使用 內容概要 示例演示和基本介紹 啟用Action Bar 在Action Bar上添加按鈕 自定義Action Bar樣式 自動
Cordova系列學習教程02 開發環境的准備和運行 主要用Eclipse來搭建環境: 下載Eclipse 安裝ADThttp://de
Android Volley 的基本使用/設置HTTP請求參數、apikey,androidapikey最近在做一個Android的新聞客戶端,感覺收獲頗豐。 這裡分享一
安卓四大組件之廣播,安卓四大組件 廣播是一種廣泛運用的在應用程序之間傳輸信息的機制,Android 為了將系統