Google Maps Android API: не удалось загрузить карту. Ошибка связи с серверами Google. Вероятно, это проблема аутентификации после реализации закрепления SSL - PullRequest
1 голос
/ 12 июня 2019

Мы внедрили SSL-пиннинг в нашем приложении после того, как эта карта Google показывает белый экран с ошибкой ниже -

Google Maps Android API: не удалось загрузить карту. Ошибка связи с Google сервера. Вероятно, это проблема аутентификации (но может быть из-за ошибки сети).

Если я удалю сертификат, карта Google будет отображаться отлично.

RequestQueue requestQueue = Volley.newRequestQueue(this, new HurlStack(null, getSocketFactory()));

 public static SSLSocketFactory getSocketFactory()
    {

        try {

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

            final String[] certificates = {"certi1.crt", "certi2.crt"};

            for (int i = 0; i < certificates.length; i++)
            {
                CertificateFactory cf = null;
                InputStream caInput = null;
                Certificate ca;
                try {
                    cf = CertificateFactory.getInstance("X.509");
                    try
                    {

                        caInput = new BufferedInputStream(context.getAssets().open("certificate/" + certificates[i]));

                    } catch (NullPointerException e)
                    {
                        e.printStackTrace();
                    }
                } catch (CertificateException e)
                {
                    e.printStackTrace();
                } catch (IOException e)
                {
                    e.printStackTrace();
                }

                try
                {
                    ca = cf.generateCertificate(caInput);
                    System.out.println("ca=" + ((X509Certificate) ca).getSubjectDN());
                }
                finally
                {
                    try
                    {
                        caInput.close();
                    } catch (IOException e)
                    {
                        e.printStackTrace();
                    }catch (NullPointerException e)
                    {
                        e.printStackTrace();
                    }
                }

                // Create a KeyStore containing our trusted CAs
                keyStore.setCertificateEntry("ca" + i, ca);
            }


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


            HostnameVerifier hostnameVerifier = new HostnameVerifier()
            {
                @Override
                public boolean verify(String hostname, SSLSession session)
                {
                    Log.e("CipherUsed", session.getCipherSuite());
                    Log.e("CipherUsed", hostname);




                    return hostname.compareTo("hostname")==0 || hostname.compareTo("maps.google.com") == 0);



                }
            };


            HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);
            SSLContext context = null;
            context = SSLContext.getInstance("TLSv1.2");
            context.init(null, tmf.getTrustManagers(), null);
            HttpsURLConnection.setDefaultSSLSocketFactory(context.getSocketFactory());
            SSLSocketFactory sf = context.getSocketFactory();//createSslSocketFactory();


            return sf;

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

        return  null;
    }

1 Ответ

0 голосов
/ 18 июня 2019
private RequestQueue getPinnedRequestQueue(Context context) throws CertificateException, IOException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException {

    CertificateFactory cf = CertificateFactory.getInstance("X.509");

    // Generate the certificate using the certificate file under res/raw/cert.cer
    InputStream caInput = new BufferedInputStream(context.getResources().openRawResource(R.raw.your_ssl_cert));
    final Certificate ca = cf.generateCertificate(caInput);
    caInput.close();

    // Create a KeyStore containing our trusted CAs
    String keyStoreType = KeyStore.getDefaultType();
    KeyStore trusted = KeyStore.getInstance(keyStoreType);
    trusted.load(null, null);
    trusted.setCertificateEntry("ca", ca);

    // Create a TrustManager that trusts the CAs in our KeyStore
    String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
    TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
    tmf.init(trusted);

    // Create an SSLContext that uses our TrustManager
    SSLContext sslContext = SSLContext.getInstance("TLSV1.2");
    sslContext.init(null, tmf.getTrustManagers(), null);

    SSLSocketFactory sf = sslContext.getSocketFactory();

    HurlStack hurlStack = new HurlStack(null, sf) {
        @Override
        protected HttpURLConnection createConnection(URL url) throws IOException {
            LogUtil.info(TAG, "Before createConnection");
            HttpsURLConnection httpsURLConnection = (HttpsURLConnection) super.createConnection(url);
            LogUtil.info(TAG, "After createConnection");
            httpsURLConnection.setHostnameVerifier(new HostnameVerifier() {

                @DebugLog
                @Override
                public boolean verify(String hostName, SSLSession sslSession) {
                    String certificateDomainName = ((X509Certificate) ca).getSubjectDN().toString();
                    LogUtil.info(TAG, "Index : " + certificateDomainName.indexOf("CN=") + " Len : " + certificateDomainName.codePointCount(certificateDomainName.indexOf("CN="), certificateDomainName.indexOf(",")));
                    String certificateName = certificateDomainName.substring(certificateDomainName.indexOf("CN="), certificateDomainName.codePointCount(certificateDomainName.indexOf("CN="), certificateDomainName.indexOf(",")));
                    certificateName = certificateName.replace("CN=", "");
                    LogUtil.info(TAG, "hostName : " + hostName + " certificateName : " + certificateName);
                    if (certificateName.isEmpty())
                        return false;
                    return certificateName.equals(hostName);
                }
            });
            return httpsURLConnection;
        }
    };

    return new Volley().newRequestQueue(context, hurlStack);
}
Instead of using requestQueue = new Volley().newRequestQueue(context);

Use requestQueue = getPinnedRequestQueue(context);
...