CertPathValidatorException : Trust anchor for certificate path not found - Retrofit Android

前端 未结 9 1997
庸人自扰
庸人自扰 2020-11-29 16:07

I am creating an android application which uses https for communication with the server. I am using retrofit and OkHttp for making req

相关标签:
9条回答
  • 2020-11-29 16:31

    Retrofit 2.3.0

        // Load CAs from an InputStream
        CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
    
        InputStream inputStream = context.getResources().openRawResource(R.raw.ssl_certificate); //(.crt)
        Certificate certificate = certificateFactory.generateCertificate(inputStream);
        inputStream.close();
    
        // Create a KeyStore containing our trusted CAs
        String keyStoreType = KeyStore.getDefaultType();
        KeyStore keyStore = KeyStore.getInstance(keyStoreType);
        keyStore.load(null, null);
        keyStore.setCertificateEntry("ca", certificate);
    
        // Create a TrustManager that trusts the CAs in our KeyStore.
        String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
        TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(tmfAlgorithm);
        trustManagerFactory.init(keyStore);
    
        TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
        X509TrustManager x509TrustManager = (X509TrustManager) trustManagers[0];
    
    
        // Create an SSLSocketFactory that uses our TrustManager
        SSLContext sslContext = SSLContext.getInstance("SSL");
        sslContext.init(null, new TrustManager[]{x509TrustManager}, null);
        sslSocketFactory = sslContext.getSocketFactory();
    
        //create Okhttp client
        OkHttpClient client = new OkHttpClient.Builder()
                    .sslSocketFactory(sslSocketFactory,x509TrustManager)
                    .build();
    
        Retrofit retrofit = new Retrofit.Builder()
                        .baseUrl(url)
                        .addConverterFactory(GsonConverterFactory.create())
                        .client(client)
                        .build();
    
    0 讨论(0)
  • 2020-11-29 16:37

    If you have a certificate then you can provide but few webservices will not have the certificate for them please follow below.

     // creating a KeyStore containing our trusted CAs
        String keyStoreType = KeyStore.getDefaultType();
        KeyStore keyStore = KeyStore.getInstance(keyStoreType);
        keyStore.load(null, null);
    
        // creating a TrustManager that trusts the CAs in our KeyStore
        String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
        tmf.init(keyStore);
    
        // creating an SSLSocketFactory that uses our TrustManager
        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(null, tmf.getTrustManagers(), null);
        okHttpClient.setSslSocketFactory(sslContext.getSocketFactory());
        // creating a RestAdapter using the custom client
        return new RestAdapter.Builder()
                .setEndpoint(UrlRepository.API_BASE)
                .setClient(new OkClient(okHttpClient))
                .build();
    
    0 讨论(0)
  • 2020-11-29 16:39

    I don't use Retrofit and for OkHttp here is the only solution for self-signed certificate that worked for me:

    1. Get a certificate from our site like in Gowtham's question and put it into res/raw dir of the project:

      echo -n | openssl s_client -connect elkews.com:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > ./res/raw/elkews_cert.crt
      
    2. Use Paulo answer to set ssl factory (nowadays using OkHttpClient.Builder()) but without RestAdapter creation.

    3. Then add the following solution to fix: SSLPeerUnverifiedException: Hostname not verified

    So the end of Paulo's code (after sslContext initialization) that is working for me looks like the following:

    ...
    OkHttpClient.Builder builder = new OkHttpClient.Builder().sslSocketFactory(sslContext.getSocketFactory());
    builder.hostnameVerifier(new HostnameVerifier() {
      @Override
      public boolean verify(String hostname, SSLSession session) {
        return "secure.elkews.com".equalsIgnoreCase(hostname);
    });
    OkHttpClient okHttpClient = builder.build();
    
    0 讨论(0)
提交回复
热议问题