溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

android下使用https協議發請求

發布時間:2020-07-24 20:01:56 來源:網絡 閱讀:1294 作者:weigq811202 欄目:移動開發

Android用Java開發,Java自帶的http API有HttpURLConnection,Android系統又加上了Apache Httpclient,后來在22版本中HttpClient又被Google刪除,所以我們不使用HttpClient來做網絡請求了,這里只給出HttpURLConnection的方式。
原生的寫法理解的沒問題了,用第三方的寫法也好弄.這里就不寫了,有需要的同學聯系我哈.我再補充

在講android連接https的請求之前,其實應該先學習一下https的知識.https是另一種協議,跟http類似,也是發一次請求request建立一次鏈接connection帶回一次信息response后再把鏈接斷開.但又增加了新的內容:在發送請求前,要先把數據用SSL加密,而接收的信息也是服務端用SSL加密后的,需要先解密后才能正常使用.這樣就確保了有人即便在網絡上抓包,也無法知道到底傳輸的數據是什么,因為別人不知道你們的密鑰是什么,比較安全.那有人就說了,客戶端client怎么和服務端server商定一個只有雙方知道的密鑰呢?啊,能這樣想就證明你已經對HTTPS的SSL加密有一些認識了.其實過程也簡單.一般來說服務端server都是些網站,都是任何人都能訪問的,但客戶端又得得到一個只有自己和server知道而其它client不知道的密鑰.其實這步也不難啊,只要client第一次訪問server時,server象管理session一樣給它一個唯一字符串,以后雙方都用這個做密鑰就好了嘛.
有了上一步的想法,好象HTTPS也很好理解,但是,人家HTTPS想的事情比這個要多.人家是這樣想的:在做某些事情之前客戶端client必須要先信任這個server不是仿冒的才跟它通信.也就是說有些事情是不能在釣魚網站(仿冒的網站,就算你搞了DNS進攻讓別人比如支付寶的域名指向你的服務器)上做的.這一步又是如何完成的呢?其實是客戶端要先有服務端的一個簽名文件(有時又叫指紋信息),也就是CA證書.終于說到服務端的CA證書了,好了,下面說對我們這次工作有用的東西,有關HTTPS和SSL的更多知識,大家可以去參考百度百科.
服務端用的CA證書,其實分為兩種,一:花了錢向一個什么中心申請注冊的,另一種是自己用工具生成一個而不去花錢注冊.
第一種,就象百度這樣的,我們可以直接象用HTTP一樣是去這樣的HTTPS的鏈接.因為這樣的,你的connection會自動從注冊中心下載證書并配置.大網站一般都這樣.
第二種,就需要做處理.要做的處理寫下面.

處理如下:
先跟服務端要一個證書文件,然后通過一大段代碼設置到我們的HttpURLConnection中.其實就是讓我們的client端信任此server.
((HttpsURLConnection) httpConn).setSSLSocketFactory(sslSocketFactory); //至于這個sslSocketFactory如何通過證書產生,哈哈.好大一段代碼,參考完整的代碼中的寫法吧.

但好象還有沒有證書的,配置就是讓HttpURLConnection相信一個沒證書的配置,然后添加信任的域名,其實可以理解為只要是域名符合我就相信啦!!靠,這client客戶端這次可以被加了dns欺騙的釣魚網站進攻了...
((HttpsURLConnection) urlConnection).setSSLSocketFactory(sslSocketFactory);
((HttpsURLConnection) urlConnection).setHostnameVerifier(SSLContextUtil.hostnameVerifier);
看,多了一行吧.
經測試,沒有證書只相信域名的這種做法,其實對那些需要證書且需要配置的網站,也能正常訪問.看來CA證書還真是僅僅只做了讓客戶端如何相信他啊,也就是防釣魚進攻.

簡單說一下什么是釣魚進攻:就是進攻者為了得到你的支付寶賬號和密碼,就做了一個跟支付寶網站看上去一樣的網站,然后想辦法引導你在他的網站上登錄你的支付寶....這就是釣魚....
所謂的DNS進攻,就是讓別人的正常域名不再指向別人的網站,比如支付寶的域名本來是指向阿里的支付寶網站服務器的ip的,但被進攻成功后,就變成了指向進攻者的釣魚網站的IP了..此時用戶就算檢查瀏覽器中地址欄的域名,也無法排除.
為了防止這樣的事情發生,HTTPS協議規定了客戶端在使用HTTPS之前,必須得先確認server服務端的身份,于是引入CA證書.為了方便客戶端client去訪問他,又引入一個什么注冊中心.

下面是我的例子的所有代碼

SSLContextUtil類,核心類.
package cn.wei.https;

import java.io.IOException;
import java.io.InputStream;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import javax.net.ssl.TrustManagerFactory;

import android.content.Context;

public class SSLContextUtil {

private static SSLContext mSSLContext;
private static SSLContext mNoCarSSLContext;
private static HostnameVerifier hostnameVerifier = new HostnameVerifier() {@Override
br/>@Override
return true;
}
};

public static SSLContext getSSLContext() {
return mSSLContext;
}
public static SSLContext getNoCarSSLContext() {
return mNoCarSSLContext;
}
public static HostnameVerifier getHostnameVerifier(){
return hostnameVerifier;
}

public static void init(Context c) {
try {
mSSLContext = getSSLContext2(c);
} catch (Exception e) {
e.printStackTrace();
}
try {
mNoCarSSLContext = getNoCarSLLContext2();
} catch (Exception e) {
e.printStackTrace();
}
}
private static SSLContext getNoCarSLLContext2() {
// SSLContext sslContext = null;
//X509TrustManager a;//為了import這個類,就得這樣寫一下.
SSLContext sslContext = null;
try {
sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, new TrustManager[]{new X509TrustManager() {@Override
br/>@Override

        @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;

}

private static SSLContext getSSLContext2(Context c)
throws NoSuchAlgorithmException, IOException, CertificateException,
KeyStoreException, UnrecoverableKeyException,
KeyManagementException {
// 生成SSLContext對象
SSLContext sslContext = SSLContext.getInstance("TLS");
// 從assets中加載證書
InputStream inStream = c.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;
}

}

Application類,輔助初始化的

public class MyApp extends Application {

@Override
public void onCreate() {
super.onCreate();
SSLContextUtil.init(this);
}
}

Activity類,使用的.

package cn.wei.https;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.widget.TextView;

public class MainActivity extends Activity {
TextView tv_html;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv_html = (TextView) this.findViewById(R.id.tv_html);

AsyncTask<String, String, String> at = new AsyncTask<String, String, String>() {

@Override
protected String doInBackground(String... params) {
HttpURLConnection httpConn = null;
try {
URL url = new URL(params[0]);
URLConnection conn = url.openConnection();
httpConn = (HttpURLConnection) conn;
// 設置SSLSocketFoactory,這里有兩種:1.需要安全證書 2.不需要安全證書;看官且往下看
if (httpConn instanceof HttpsURLConnection) { // 是Https請求
// 0.需要證書但不需要配的.什么也不用寫.比如百度的https://www.baidu.com
// 1.需要安全證書且需要配的.
// SSLContext sslContext = SSLContextUtil.getSSLContext();
// if (sslContext != null) {
// SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
// ((HttpsURLConnection) httpConn).setSSLSocketFactory(sslSocketFactory);
//
//
// }
// 2.不需要安全證書但需要配的:server端有但沒給,client端配置直接相信此域名.
// SSLContext sslContext = SSLContextUtil.getNoCarSSLContext();
// if (sslContext != null) {
// SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
// ((HttpsURLConnection) httpConn).setSSLSocketFactory(sslSocketFactory);
// ((HttpsURLConnection) httpConn).setHostnameVerifier(SSLContextUtil.getHostnameVerifier());
// }
}
httpConn.setRequestMethod("GET");
httpConn.setReadTimeout(16000);
httpConn.setConnectTimeout(16000);
int resCode = httpConn.getResponseCode();
if (resCode == 200) {
try (InputStream in = httpConn.getInputStream();
Reader r = new InputStreamReader(in, "UTF-8");
BufferedReader br = new BufferedReader(r);) {
String line = null;
StringBuilder sb = new StringBuilder();
do {
line = br.readLine();
sb.append(line).append("\n");
} while (line != null);
return sb.toString();
} catch (IOException e) {
throw e;
}
} else {
return "網絡請求錯誤.resCode:" + resCode;
}
} catch (MalformedURLException e) {
e.printStackTrace();
return "err:" + e.getMessage();
} catch (IOException e) {
e.printStackTrace();
return "err:" + e.getMessage();
} finally {
httpConn.disconnect();
}

}

@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
tv_html.setText(result);

}

};
//at.execute("https://kyfw.12306.cn/otn/");//這個是有證書需要配的.
//at.execute("https://www.baidu.com");//百度是有證書但不用配的.
at.execute("https://www.alipay.com/");//有證書但不用配的.

}

}

.

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女