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

前端 未结 11 744
清酒与你
清酒与你 2020-11-27 15:59

I am using Retrofit to access my REST API. However, when I put my API behind ssl and access it by http://myhost/myapi then I get this error:

Do I need t

11条回答
  •  温柔的废话
    2020-11-27 16:35

    OK, So I faced the same issue for my android app which have secured domain i.e. HTTPS,

    These are the steps:

    1. You need SSL certificate file i.e. ".pem" file for your domain.
    2. put that file into the assets folder
    3. Just copy and paste this class in your project

    public class SSlUtilsw {

    public static SSLContext getSslContextForCertificateFile(Context context, String fileName){
    
        try {
            KeyStore keyStore = SSlUtilsw.getKeyStore(context, fileName);
            SSLContext sslContext = SSLContext.getInstance("SSL");
            TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
            trustManagerFactory.init(keyStore);
            sslContext.init(null,trustManagerFactory.getTrustManagers(),new SecureRandom());
            return sslContext;
    
        }catch (Exception e){
            String msg = "Error during creating SslContext for certificate from assets";
            e.printStackTrace();
            throw new RuntimeException(msg);
        }
    }
    
    public static KeyStore getKeyStore(Context context,String fileName){
        KeyStore keyStore = null;
        try {
            AssetManager assetManager=context.getAssets();
            CertificateFactory cf = CertificateFactory.getInstance("X.509");
            InputStream caInput=assetManager.open(fileName);
            Certificate ca;
            try {
                ca=cf.generateCertificate(caInput);
    
            }finally {
                caInput.close();
            }
            String keyStoreType=KeyStore.getDefaultType();
            keyStore=KeyStore.getInstance(keyStoreType);
            keyStore.load(null,null);
            keyStore.setCertificateEntry("ca",ca);
        } catch (CertificateException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (KeyStoreException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return keyStore;
    }}
    
    1. In your http client class of retrofit, add this

          val trustManagerFactory: TrustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm())
      trustManagerFactory.init(null as KeyStore?)
      val trustManagers: Array = trustManagerFactory.trustManagers
      if (trustManagers.size != 1 || trustManagers[0] !is X509TrustManager) {
          throw IllegalStateException("Unexpected default trust managers:" + trustManagers.contentToString())
      }
      val trustManager = trustManagers[0] as X509TrustManager
      
      httpClient.sslSocketFactory(SSlUtils.getSslContextForCertificateFile(
              applicationContextHere, "yourcertificate.pem").socketFactory, trustManager)
      

    And that's it.

提交回复
热议问题