编辑
Okhttp请求https接口报错
本文访问次数:0

使用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.

出现这种问题的情况有两种

  1. CA颁发的证书,但是服务器配置错误
  2. CA颁发的证书,服务器正确
  3. 自签名的证书

第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)

  • 宗仁 2017/04/07 回复 编辑 删除

    第1种情况应该是没有安装中间证书(intermediate certificate)