1、demo演示
通过OkHttp拉取网页信息,为OkHttp设置证书验证
以知网为例,https://www.cnki.net/
文件夹中未放置知网证书时,
文件夹中放置了知网证书时,
2、代码
依赖
//BindView
implementation 'com.jakewharton:butterknife:10.2.1'
annotationProcessor 'com.jakewharton:butterknife-compiler:10.2.1'
//okHttp
implementation 'com.squareup.okhttp3:okhttp:3.10.0'
implementation 'com.squareup.okhttp3:logging-interceptor:3.4.1'
权限
<uses-permission android:name="android.permission.INTERNET" />
1)数据处理
- OkHttpManager
public class OkHttpManager {
public static final String TAG = "OkHttpManager";
/**
* CERT_ALIAS 证书别名
*/
public static final String CERT_ALIAS = "NCB";
/**
* CONNECT_TIME_OUT 连接超时
* READ_TIME_OUT 读超时
* WRITE_TIME_OUT 写超时
*/
public static final int CONNECT_TIME_OUT = 75;
public static final int READ_TIME_OUT = 75;
public static final int WRITE_TIME_OUT = 75;
/**
* instance 单例
* INSTANCE_LOCK 互斥锁
*/
private static OkHttpManager instance = null;
private static final Object INSTANCE_LOCK = new Object();
/**
* 获取单例
*
* @return
*/
public static OkHttpManager getInstance() {
if (instance == null) {
synchronized (INSTANCE_LOCK) {
if (instance == null) {
instance = new OkHttpManager();
}
}
}
return instance;
}
/**
* 获取本地证书
*
* @return
*/
private ArrayList<Certificate> getCertificatesFromAssets(Context context) {
ArrayList<Certificate> certificates = new ArrayList<>();
try {
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
String certPath = "certs";
AssetManager am = context.getAssets();
String[] list = am.list(certPath);
for (int i = 0; i < list.length; i++) {
certificates.add(certificateFactory.generateCertificate(am.open(certPath + "/" + list[i])));
Log.i(TAG, "cer name:" + certPath + "/" + list[i]);
}
return certificates;
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG, e.getMessage());
}
return null;
}
/**
* 获取含证书校验功能的 OkHttpClientBuilder
*
* @param context
* @return
*/
public OkHttpClient.Builder getOkHttpClientBuilderWithCerts(Context context) {
OkHttpClient.Builder builder = new OkHttpClient.Builder();
try {
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null);
ArrayList<Certificate> localCerts = getCertificatesFromAssets(context);
for (int i = 0; i < localCerts.size(); i++) {
keyStore.setCertificateEntry(CERT_ALIAS + i, localCerts.get(i));
}
SSLContext sslContext = SSLContext.getInstance("TLS");
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keyStore);
sslContext.init(null, trustManagerFactory.getTrustManagers(), new SecureRandom());
SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
final X509TrustManager trustManager = new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
};
builder.sslSocketFactory(sslSocketFactory, trustManager);
HostnameVerifier hostnameVerifier = new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
builder.hostnameVerifier(hostnameVerifier);
builder.connectTimeout(CONNECT_TIME_OUT, TimeUnit.SECONDS)
.readTimeout(READ_TIME_OUT, TimeUnit.SECONDS)
.writeTimeout(WRITE_TIME_OUT, TimeUnit.SECONDS);
return builder;
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG, e.getMessage());
}
return null;
}
}
- DataManager
/**
* @description 数据处理层
*/
public class DataManager {
/**
* 从服务器获取数据
*
* @param url 请求url
* @param dataCallback 回调
*/
public static void getDataFromServer(Context context, String url, final DataCallback dataCallback) {
OkHttpClient.Builder builder = OkHttpManager.getInstance().getOkHttpClientBuilderWithCerts(context);
Request request = new Request.Builder().url(url).build();
builder.build().newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
dataCallback.getDataFailed(e.getMessage());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
InputStream inputStream = response.body().byteStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
StringBuilder stringBuilder = new StringBuilder();
String line = "";
while ((line = reader.readLine()) != null) {
stringBuilder.append(line);
}
dataCallback.getDataSuccess(stringBuilder.toString());
}
});
}
}
- ViewModel
public class DataViewModel extends ViewModel {
/**
* liveData LiveData
*/
private MutableLiveData<String> liveData;
/**
* 构造函数
*/
public DataViewModel() {
liveData = new MutableLiveData<>();
}
/**
* 获取 LiveData
*
* @return
*/
public MutableLiveData<String> getLiveData() {
return liveData;
}
/**
* 获取网站数据
*
* @param context
* @param url
*/
public void getDataFromServer(Context context, String url) {
DataManager.getDataFromServer(context, url, new DataCallback() {
@Override
public void getDataSuccess(String data) {
liveData.postValue("data : \n\n" + data);
}
@Override
public void getDataFailed(String errMsg) {
liveData.postValue("error message \n\n: " + errMsg);
}
});
}
}
2)界面布局
- BaseActivity
abstract public class BaseActivity extends AppCompatActivity {
private Unbinder unbinder = null;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(getLayoutId());
unbinder = ButterKnife.bind(this);
init();
}
abstract protected int getLayoutId();
abstract protected void init();
protected BaseActivity getActivity() {
return this;
}
@Override
protected void onDestroy() {
super.onDestroy();
if (unbinder != null) {
unbinder.unbind();
}
}
}
- Activity
public class OkHttpActivity extends BaseActivity {
//知网
public static final String TEST_URL = "https://www.cnki.net/";
private DataViewModel dataViewModel;
@BindView(R.id.id_btn_get_data)
TextView btnGetData;
@BindView(R.id.id_tv_show_data)
TextView tvShowData;
@Override
protected int getLayoutId() {
return R.layout.act_ok_http;
}
@Override
protected void init() {
dataViewModel = new ViewModelProvider(this, new ViewModelProvider.NewInstanceFactory()).get(DataViewModel.class);
dataViewModel.getLiveData().observe(this, new Observer<String>() {
@Override
public void onChanged(String s) {
tvShowData.setText(s);
}
});
tvShowData.setMovementMethod(ScrollingMovementMethod.getInstance());
btnGetData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dataViewModel.getDataFromServer(getActivity(), TEST_URL);
}
});
}
}
- layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/id_btn_get_data"
style="@style/ButtonNormalStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="20dp"
android:background="@color/black"
android:text="get data" />
<TextView
android:id="@+id/id_tv_show_data"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="20dp"
android:fadeScrollbars="false"
android:scrollbarSize="10dp"
android:scrollbars="vertical"
android:text="result"
android:textSize="30dp" />
</LinearLayout>
3、使用谷歌浏览器下载网站证书
以知网为例:https://www.cnki.net/
1、点击“锁”图标
2、点击证书
3、详细信息 -> 复制文件
4、下一页
5、保存
6、完成