1、问题:
项目下载改为 https 协议,连接代理后使用 liulishuo 的 FileDownLoader 无法下载,抛出异常如下:
javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
2、原因:
没有信任证书或该域名的根证书不被信任
3、解决方案:
方案一:添加证书文件,参考这篇博客;
方案二:在程序中绕过证书校验;
本文采用的是方案二,绕过证书校验。具体步骤如下:
自定制 OkHttp3Connection 替换 FileDownload 的默认连接方式(FileDownloadUrlConnection)
在创建 OkHttpClient.Builder 的时候复写 hostnameVerifier ,并创建TrustManager 忽略 SSL 验证
使用FileDownloader.setupOnApplicationOnCreate(this).connectionCreator(....)的方式注册 FileDownloader
FileDownLoader 初始化代码:
public class FileDownloaderHelper {
// 超时设置 单位 秒
private static final int READ_TIMEOUT = 5 * 60;
private static final int WRITE_TIMEOUT = 5 * 60;
private static final int CONNECT_TIMEOUT = 30;
/**
* 在主进程的 Application 的 onCreate 里调用
*/
public static void setup(Application application) {
FileDownloader.setup(application);
}
/**
* 在 FileDownLoader 进程的 Application 的 onCreate 里调用,绕过 SSL 认证代码如果不在 FileDownLoader 进程调用也无效
*/
public static void initInDownloadProcess(Application application) {
OkHttpClient.Builder builder = new OkHttpClient.Builder()
.readTimeout(READ_TIMEOUT, TimeUnit.SECONDS)
.writeTimeout(WRITE_TIMEOUT, TimeUnit.SECONDS)
.connectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS);
// 添加 SSL 认证
SSLTrustManager.addVerify(builder);
FileDownloader.setupOnApplicationOnCreate(application)
.connectionCreator(new OkHttp3Connection.Creator(builder))// 自实现 OkHttp3Connection
.commit();
}
}
看下如何绕过 SSL 认证,代码如下:
public class SSLTrustManager {
public static void addVerify(OkHttpClient.Builder builder) {
if (builder == null) {
return;
}
builder.hostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
// 这里是所有域名都绕过 SSL 验证,最好是只添加信任的域名
return true;
}
});
SSLContext sslContext = null;
try {
sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, new TrustManager[]{xtm}, new SecureRandom());
builder.sslSocketFactory(sslContext.getSocketFactory(), xtm);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
} catch (Exception e){
e.printStackTrace();
}
}
private static X509TrustManager xtm = new X509TrustManager() {
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) {
}
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
X509Certificate[] x509Certificates = new X509Certificate[0];
return x509Certificates;
}
};
}
OkHttp3Connection 实现如下:
public class OkHttp3Connection implements FileDownloadConnection {
private OkHttpClient mClient;
private Request.Builder mRequestBuilder;
private Request mRequest;
private Response mResponse;
public OkHttp3Connection(String url, OkHttpClient client) {
try {
mRequestBuilder = new Request.Builder().url(url);
mClient = client;
} catch (Exception e) {
LogUtil.e(e.getMessage());
}
}
@Override
public void addHeader(String name, String value) {
mRequestBuilder.addHeader(name, value);
}
@Override
public boolean dispatchAddResumeOffset(String etag, long offset) {
return false;
}
@Override
public InputStream getInputStream() throws IOException {
if (mResponse == null) throw new IllegalStateException("Please invoke #execute first!");
return mResponse.body().byteStream();
}
@Override
public Map<String, List<String>> getRequestHeaderFields() {
if (mRequest == null) {
mRequest = mRequestBuilder.build();
}
return mRequest.headers().toMultimap();
}
@Override
public Map<String, List<String>> getResponseHeaderFields() {
return mResponse == null ? null : mResponse.headers().toMultimap();
}
@Override
public String getResponseHeaderField(String name) {
return mResponse == null ? null : mResponse.header(name);
}
@Override
public boolean setRequestMethod(String method) throws ProtocolException {
return true;
}
@Override
public void execute() throws IOException {
if (mRequest == null) {
mRequest = mRequestBuilder.build();
}
mResponse = mClient.newCall(mRequest).execute();
}
@Override
public int getResponseCode() throws IOException {
if (mResponse == null) throw new IllegalStateException("Please invoke #execute first!");
return mResponse.code();
}
@Override
public void ending() {
mRequest = null;
mResponse = null;
}
/**
* The creator for the connection implemented with the okhttp3.
*/
public static class Creator implements FileDownloadHelper.ConnectionCreator {
private OkHttpClient mClient;
private OkHttpClient.Builder mBuilder;
public Creator() {
}
/**
* Create the Creator with the customized {@code client}.
*
* @param builder the builder for customizing the okHttp client.
*/
public Creator(OkHttpClient.Builder builder) {
mBuilder = builder;
}
@Override
public OkHttp3Connection create(String url) throws IOException {
if (mClient == null) {
synchronized (Creator.class) {
if (mClient == null) {
mClient = mBuilder != null ? mBuilder.build() : new OkHttpClient();
mBuilder = null;
}
}
}
return new OkHttp3Connection(url, mClient);
}
}
}
大功告成!
参考链接: