使用okhttp请求https协议的接口时,提示以下错误:
javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
Caused by: java.security.cert.CertificateException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
出现这种问题的情况有两种
- CA颁发的证书,但是服务器配置错误
- CA颁发的证书,服务器正确
- 自签名的证书
第1中情况暂时不知道怎么解决
第2种情况按照以下方式解决:stackoverflow
首先把证书放在raw文件夹内
src/main/res/raw/keystore.bks
然后创建okHttpClient
private OkHttpClient customClient() {
OkHttpClient okHttpClient = null;
try {
KeyStore keystore = KeyStore.getInstance("BKS");
InputStream inputStream = context.getResources().openRawResource(R.raw.keystore);
keystore.load(inputStream, "secret".toCharArray());
// TrustManager decides which certificate authorities to use.
TrustManagerFactory trustManagerFactory = TrustManagerFactory
.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keystore);
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, trustManagerFactory.getTrustManagers(), null);
okHttpClient = new OkHttpClient.Builder()
.sslSocketFactory(sslContext.getSocketFactory())
.build();
} catch (IOException | CertificateException | NoSuchAlgorithmException | KeyStoreException | KeyManagementException e) {
e.printStackTrace();
}
return okHttpClient;
}
第3种情况可以参考这篇文章:Android Https相关完全解析 当OkHttp遇到Https
还有一种解决办法就是跳过证书验证
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(url)
.client(getUnsafeOkHttpClient())
.build();
getUnsafeOkHttpClient
方法如下
private static OkHttpClient getUnsafeOkHttpClient() {
try {
// Create a trust manager that does not validate certificate chains
final TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
@Override
public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return new java.security.cert.X509Certificate[0];
}
}
};
// Install the all-trusting trust manager
final SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
// Create an ssl socket factory with our all-trusting manager
final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
HostnameVerifier verifier = new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
return new OkHttpClient.Builder()
.sslSocketFactory(sslSocketFactory)
.hostnameVerifier(verifier)
.build();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
P.S. 第1种情况应该是没有安装中间证书(intermediate certificate)