一、概述
其实这篇文章理论上不限于okhttp去访问自签名的网站,不过接上篇博文了,就叫这个了。首先要了解的事,okhttp默认情况下是支持https协议的网站的,比如https://www.baidu.com,https://github.com/hongyangAndroid/okhttp-utils等,你可以直接通过okhttp请求试试。不过要注意的是,支持的https的网站基本都是CA机构颁发的证书,默认情况下是可以信任的。
当然我们今天要说的是自签名的网站,什么叫自签名呢?就是自己通过keytool去生成一个证书,然后使用,并不是CA机构去颁发的。使用自签名证书的网站,大家在使用浏览器访问的时候,一般都是报风险警告,如下界面:使用 okhttp 进行访问时未信任的安全网站时会提示
javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
或
javax.net.ssl.SSLPeerUnverifiedException: Hostname xxxx.com not verified:
二、解决办法
解决办法有两种
信任所有的证书(开发测试使用)
导入自签名证书
1、信任所有的证书
信任所有的证书后可以成功解决掉不能访 https 自签名地址的问题,但这样也就失去了使用自签名的意义。开发过程中可以使用这种方式屏蔽掉自签名,需要使用到无法获得证书的地址的资源时也可以使用这种方式。
实现代码
import okhttp3.OkHttpClient;
import javax.net.ssl.*;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
/**
* 封装的支持Https连接工具类
*/
public class HttpsUtils {
private MyTrustManager mMyTrustManager;
private SSLSocketFactory createSSLSocketFactory() {
SSLSocketFactory ssfFactory = null;
try {
mMyTrustManager = new MyTrustManager();
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, new TrustManager[]{mMyTrustManager}, new SecureRandom());
ssfFactory = sc.getSocketFactory();
} catch (Exception ignored) {
ignored.printStackTrace();
}
return ssfFactory;
}
/**
* 实现X509TrustManager接口
*/
public class MyTrustManager implements 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];
}
}
/**
* 实现HostnameVerifier接口(信任所有的 https 证书。)
*/
private class TrustAllHostnameVerifier implements HostnameVerifier {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
}
public OkHttpClient getTrustAllClient() {
OkHttpClient.Builder mBuilder = new OkHttpClient.Builder();
mBuilder.sslSocketFactory(createSSLSocketFactory(), mMyTrustManager)
.hostnameVerifier(new TrustAllHostnameVerifier());
return mBuilder.build();
}
}实现步骤:
创建实现 HostnameVerifier 接口的类并重写他的
verify方法使其直接返回true;创建实现 X509TrustManager 接口的类并重写
getAcceptedIssuers()使其返回 new X509Certificate[0];构建 SSL 工厂
SSLSocketFactory即上面代码中的createSSLSocketFactory()方法;使用 OkHttpClient.Builder 中设置 sslSocketFactory(
构建的工厂,实现的 TrustManager 类),此处的 TurstManager 需要保持跟 Factory 中使用的 TrustManager 是同一个实例。设置 hostnameVerifier 为构建的 HostnameVerifier;
2、导入自签名证书
信任所有证书虽然能解决不能访问 https 服务器地址的问题,但安全性被忽视掉了。显然是不符合要求的,用 https 就是为了安全性跳过 验证也就失去了他的意义了。好在我们还有其他的方法来解决----导入自签名的证书。
未完带补充。。。
未经允许请勿转载:程序喵 » OkHttp3之Https访问(五)
程序喵