社区微信群开通啦,扫一扫抢先加入社区官方微信群
社区微信群
最近公司项目要求APP客户端与服务端通讯时经过https协议,但是初次搭的https环境没有安全的数字证书,是JDK生成的证书,APP访问过程中遇到了一些问题。
报了一个这样的错
javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
百度了一下是数字证书的问题,但是我的客户端请求框架是OkHttp
原先用的是
'com.ansen.http:okhttpencapsulation:1.0.1'
这个框架去做请求以及下载文件的
主要用到的类HTTPCaller.java的源码当中,可以看到它对OkHttp的使用
/**
* 设置配置信息 这个方法必需要调用一次
* @param httpConfig
*/
public void setHttpConfig(HttpConfig httpConfig) {
this.httpConfig = httpConfig;
client = new OkHttpClient.Builder()
.connectTimeout(httpConfig.getConnectTimeout(), TimeUnit.SECONDS)
.writeTimeout(httpConfig.getWriteTimeout(), TimeUnit.SECONDS)
.readTimeout(httpConfig.getReadTimeout(), TimeUnit.SECONDS)
.build();
gson = new Gson();
requestHandleMap = Collections.synchronizedMap(new WeakHashMap<String, Call>());
cacheControl =new CacheControl.Builder().noStore().noCache().build();//不使用缓存
}
通过HttpConfig类去设置配置信息,然后好像没法直接屏蔽验证数字证书
最后我决定直接用OkHttp,使用方法参考了一下两篇文章~
https://www.cnblogs.com/maomishen/p/5403301.html
https://www.jb51.net/article/117675.htm
工具类OkHttpUtil.java
package com.gotop.sanqinapp.util;
import java.io.IOException;
import java.lang.reflect.Field;
import java.security.SecureRandom;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import okhttp3.Callback;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
/**
* @Author:Swallow
* @Date:2019/7/4
**/
public class OkHttpUtil {
private static OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(20*1000, TimeUnit.MILLISECONDS)
.readTimeout(20*1000,TimeUnit.MILLISECONDS)
.writeTimeout(20*1000,TimeUnit.MILLISECONDS).build();
//绕开数字证书的方法
public static void setHttpConfig() {
SSLContext sc = null;
try {
sc = SSLContext.getInstance("SSL");
sc.init(null, new TrustManager[]{new X509TrustManager() {
@Override
public void checkClientTrusted(
java.security.cert.X509Certificate[] chain, String authType)
throws java.security.cert.CertificateException {
}
@Override
public void checkServerTrusted(
java.security.cert.X509Certificate[] chain, String authType)
throws java.security.cert.CertificateException {
}
@Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
}}, new SecureRandom());
} catch (Exception e) {
e.printStackTrace();
}
HostnameVerifier hv1 = new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
String workerClassName="okhttp3.OkHttpClient";
try {
Class workerClass = Class.forName(workerClassName);
Field hostnameVerifier = workerClass.getDeclaredField("hostnameVerifier");
hostnameVerifier.setAccessible(true);
hostnameVerifier.set(client, hv1);
Field sslSocketFactory = workerClass.getDeclaredField("sslSocketFactory");
sslSocketFactory.setAccessible(true);
sslSocketFactory.set(client, sc.getSocketFactory());
} catch (Exception e){
e.printStackTrace();
}
}
public static String sendGetSSL(Map<String, String> map, String url) throws IOException {
setHttpConfig();
String result = "";
StringBuilder reqUrl = new StringBuilder(url);
if (map != null && map.size() > 0) {
reqUrl.append("?");
for (Map.Entry<String, String> param : map.entrySet()) {
reqUrl.append(param.getKey() + "=" + param.getValue() + "&");
}
url = reqUrl.subSequence(0, reqUrl.length() - 1).toString();
}
Request request = new Request.Builder()
.url(url)
.get()
.build();
try (Response response = client.newCall(request).execute()) {
result = response.body().string();
}
return result;
}
public static void downloadFile(String url, final ProgressListener listener, Callback callback){
setHttpConfig();
OkHttpClient okHttpClient = client.newBuilder().addNetworkInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Response response = chain.proceed(chain.request());
return response.newBuilder().body(new ProgressResponseBody(response.body(),listener)).build();
}
}).build();
Request request = new Request.Builder().url(url).build();
okHttpClient.newCall(request).enqueue(callback);
}
}
下载更新apk
/**
* 开始下载
* @param downloadUrl 下载url
* @param context 当前context
*/
public static void startUpload(String downloadUrl, final Context context){
//显示进度条对话框
progressDialog=new ProgressDialog(context);
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressDialog.setMessage("正在下载新版本");
progressDialog.setCancelable(false);//不能手动取消下载进度对话框
final String fileSavePath=Utils.getSaveFilePath(downloadUrl);
//下载文件并且显示进度条
OkHttpUtil.downloadFile(downloadUrl, new ProgressListener() {
@Override
public void onProgress(long currentBytes, long contentLength, boolean done) {
//文件最大长度
progressDialog.setMax((int)contentLength);
//已下载进度
progressDialog.setProgress((int)currentBytes);
progressDialog.show();
if(done) {
openAPK(fileSavePath,context);
}
}
}, new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if (response != null) {
InputStream is = response.body().byteStream();
FileOutputStream fos = new FileOutputStream(fileSavePath);
int len = 0;
byte[] buffer = new byte[2048];
while (-1 != (len = is.read(buffer))) {
fos.write(buffer, 0, len);
}
fos.flush();
fos.close();
is.close();
}
}
});
}
/**
* 下载完成安装apk
* @param fileSavePath
*/
private static void openAPK(String fileSavePath, Context context){
File file=new File(fileSavePath);
Intent intent = new Intent(Intent.ACTION_VIEW);
Uri data;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
data = FileProvider.getUriForFile(context, "com.gotop.sanqinapp.fileprovider", file);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);// 给目标应用一个临时授权
} else {
data = Uri.fromFile(file);
}
intent.setDataAndType(data, "application/vnd.android.package-archive");
context.startActivity(intent);
}
更新过程当中会遇到权限问题,AndroidManifest.xml文件中加入
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
安卓6.0以上需要动态获取权限,使用方法可以参考这里
最后,问题解决,能够访问https并且下载文件,更新版本,显示进度条,yes
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!