java.security.cert.CertPathValidatorException: Trust anchor for certification path not found. on api less 24

爷,独闯天下 提交于 2020-02-14 06:47:06

问题


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

I got this error in logcat on api from 19 to 24 and there is no data loading from the server in my app I searched about that error and find that solution

 @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) {
    }
}

and call it in my application class onCreate and that's solved my problem but in that answer which if find that solution there is a hint This code is not relevant and shouldn't be used! it is forbidden by Google.

so anyone knows what's the alternative solution allowed by google for that error?


回答1:


first you will need to generate your certificate file and here is the steps

  • go to your website link on Firefox browser

  • click on the green lock on the right of website link

  • click on more info then view certificate

  • a new window will appear with two taps general and details choose details

  • click on export to export your certificate and save this file in android project assets.

second in you project application class define hurlStack variable and use the next method in application OnCreate Method

 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();
    }

}

and on volley requestQueue use hurlStack

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

third if you use Glide for images you will got a second error with ssl certificate related to glide and you will need to solve it by this way

1 - update in app build your gilde and okhttp3 to these version

    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 - add the next class to your project

@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);
      }
   }

 }

and now glide will work fine with you.




回答2:


What is the TLS version on your server? Most likely it is 1.2 or higher. For kitkat devices, 1.2 is off by default and needs to be enabled. If your devices have Google play services you can do this via that. Otherwise you need a custom socket factory class which specifies 1.2 and probably 1.3.

If it is lower than 1.2, post Kitkat devices will not permit connections unless you trust all certs with the hack in your question. It should not be lower.



来源:https://stackoverflow.com/questions/55992416/java-security-cert-certpathvalidatorexception-trust-anchor-for-certification-pa

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!