8
com.android.volley.NoConnectionError: javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.

我在 19 到 24 的 api 上的 logcat 中收到此错误,并且在我的应用程序中没有从服务器加载数据我搜索了该错误并找到了该解决方案

 @SuppressLint("TrulyRandom")
public static void handleSSLHandshake() {
    try {
        TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
            public X509Certificate[] getAcceptedIssuers() {
                return new X509Certificate[0];
            }

            @Override
            public void checkClientTrusted(X509Certificate[] certs, String authType) {
            }

            @Override
            public void checkServerTrusted(X509Certificate[] certs, String authType) {
            }
        }};

        SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, trustAllCerts, new SecureRandom());
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
        HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
            @Override
            public boolean verify(String arg0, SSLSession arg1) {
                return true;
            }
        });
    } catch (Exception ignored) {
    }
}

并在我的应用程序类 onCreate 中调用它,这解决了我的问题,但在那个答案中,如果找到该解决方案,则会出现提示此代码不相关且不应使用!谷歌禁止它。

所以有人知道谷歌针对该错误允许的替代解决方案是什么?

4

2 回答 2

4

首先你需要生成你的证书文件,这里是步骤

  • 在 Firefox 浏览器上访问您的网站链接

  • 点击网站链接右侧的绿色锁

  • 点击更多信息然后查看证书

  • 将出现一个新窗口,点击两次一般和详细信息选择详细信息

  • 单击导出以导出您的证书并将此文件保存在 android 项目资产中。

项目应用程序类中的第二个定义 hurlStack 变量并在应用程序 OnCreate 方法中使用下一个方法

 private void handleCertificationOnOlderDevices() {
    try {

        CertificateFactory cf = CertificateFactory.getInstance("X.509");
        InputStream caInput = new 
                            BufferedInputStream(getAssets().open("porter_cert.crt"));
        Certificate ca;
        try {
            ca = cf.generateCertificate(caInput);
            Log.d("certificate", ((X509Certificate) ca).getSubjectDN().toString());
        } finally {
            caInput.close();
        }

        String keyStoreType = KeyStore.getDefaultType();
        KeyStore keyStore = KeyStore.getInstance(keyStoreType);
        keyStore.load(null, null);
        keyStore.setCertificateEntry("ca", ca);

        String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
        tmf.init(keyStore);

        TrustManager[] trustManagers = tmf.getTrustManagers();
        final X509TrustManager origTrustmanager =  
                                                (X509TrustManager) trustManagers[0];

        TrustManager[] wrappedTrustManagers = new TrustManager[]{
                new X509TrustManager() {
                   public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                        return origTrustmanager.getAcceptedIssuers();
                   }

                   public void checkClientTrusted(X509Certificate[] certs,  
                   String authType) 
                   {
                        try {
                            origTrustmanager.checkClientTrusted(certs, authType);
                        } catch (CertificateException e) {
                            e.printStackTrace();
                        }
                    }

                    public void checkServerTrusted(X509Certificate[] certs,
                    String authType) 
                    {
                        try {
                            origTrustmanager.checkServerTrusted(certs, authType);
                        } catch (CertificateException e) {
                            e.printStackTrace();
                        }
                    }
                }
        };

        SSLContext context = SSLContext.getInstance("TLS");
        context.init(null, tmf.getTrustManagers(), null);

        SSLSocketFactory sslSocketFactory = context.getSocketFactory();
        hurlStack = new HurlStack(null, sslSocketFactory);

    } catch (Exception e) {
        e.printStackTrace();
    }

}

并在凌空请求队列上使用 hurlStack

    public RequestQueue getRequestQueue() {
       if (requestQueue == null)
           requestQueue = Volley.newRequestQueue(getApplicationContext(), 
           hurlStack);
       return requestQueue;
    }

第三,如果您将 Glide 用于图像,您将收到与 glide 相关的 ssl 证书的第二个错误,您需要通过这种方式解决它

1 - 在应用程序中更新将您的 gilde 和 okhttp3 构建到这些版本

    implementation "com.squareup.okhttp3:okhttp:3.8.1"
    implementation 'com.github.bumptech.glide:glide:4.9.0'
    annotationProcessor 'com.github.bumptech.glide:compiler:4.9.0'
    implementation ('com.github.bumptech.glide:okhttp3-integration:4.9.0'){
    exclude group: 'glide-parent'
    }

2 - 将下一个类添加到您的项目中

@GlideModule 
public class CustomGlideModule extends AppGlideModule {
   @Override
   public void registerComponents(Context context, Glide glide,  
   Registryregistry) {
      if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.N) {
          OkHttpClient client = 
                        SafeOkHttpClient.getSafeOkHttpClient(context);
          OkHttpUrlLoader.Factory factory = new 
                                       OkHttpUrlLoader.Factory(client);
          glide.getRegistry().replace(GlideUrl.class, InputStream.class, 
          factory);
      }
   }

 }

现在 glide 可以很好地配合你了。

于 2019-05-20T08:10:45.670 回答
2

您的服务器上的 TLS 版本是什么?很可能是 1.2 或更高。对于 kitkat 设备,1.2 默认是关闭的,需要启用。如果你的设备有谷歌播放服务,你可以通过它来做到这一点。否则,您需要一个自定义套接字工厂类,它指定 1.2 并且可能是 1.3。

如果它低于 1.2,则发布 Kitkat 设备将不允许连接,除非您信任问题中的所有 hack 证书。它不应该更低。

于 2019-05-06T11:01:29.550 回答