Как импортировать самоподписанный SSL-сертификат в Volley на Android 4.1+

Я разрабатываю приложение для Android, которое использует Volley. Вся связь осуществляется через соединение HTTPS. Поскольку я тестирую его в локальной среде, я использую самозаверяющие сертификаты для Tomcat.

Раньше у меня были только устройства Android 2.3 и 3.0. Теперь у меня также есть 4.1 и 4.4.

Моя реализация использует этот подход: http://developer.android.com/training/articles/security-ssl.html (часть Неизвестный центр сертификации) На устройствах с Android до 4.1 он работает отлично. SSLSocketFactory с пользовательскими сертификатами передается волейболу:

Volley.newRequestQueue(getApplicationContext(), new HurlStack(null, socketFactory));

Но что происходит на Android 4.1+? Почему это не работает? Я также пробовал с NullX509TrustManager следующим образом:

private static class NullX509TrustManager implements X509TrustManager {
    @Override
    public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType)
            throws CertificateException {
    }

    @Override
    public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType)
            throws CertificateException {
    }

    @Override
    public java.security.cert.X509Certificate[] getAcceptedIssuers() {
        return null;
    }
}

Но он по-прежнему не работает...

Ответ 1

Я разрешил это решение, упомянутое здесь:

http://developer.android.com/training/articles/security-ssl.html

Общие проблемы с проверкой имени хоста

добавив собственный верификатор имени хоста, который возвращает true для моего имени хоста в проекте Volley и редактирует метод OpenConnection HurlStack:

if ("https".equals(url.getProtocol()) && mSslSocketFactory != null) {            
    ((HttpsURLConnection)connection).setSSLSocketFactory(mSslSocketFactory);
    ((HttpsURLConnection)connection).setHostnameVerifier(new CustomHostnameVerifier());         
}

Ответ 2

Если у вас уже есть файл .crt и вы хотите прикрепить его к Volley, то вам нужно выполнить 2 простых шага.

Шаг 1: Напишите этот метод в своем коде.

public SSLSocketFactory getSocketFactory(Context context)
        throws CertificateException, IOException, KeyStoreException, NoSuchAlgorithmException, KeyManagementException {

    // Load CAs from an InputStream (could be from a resource or ByteArrayInputStream or ...)
    CertificateFactory cf = CertificateFactory.getInstance("X.509");

    InputStream caInput = new BufferedInputStream(context.getResources().openRawResource(R.raw.myFile));
                                                   // I paste my myFile.crt in raw folder under res.
    Certificate ca;

    //noinspection TryFinallyCanBeTryWithResources
    try {
        ca = cf.generateCertificate(caInput);
        System.out.println("ca=" + ((X509Certificate) ca).getSubjectDN());
    } finally {
        caInput.close();
    }

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

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

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

    return sslContext.getSocketFactory();
}

Шаг 2: Просто добавьте эту строку ниже, прежде чем делать любой запрос, используя Volley.

HttpsURLConnection.setDefaultSSLSocketFactory(getSocketFactory(context));

Android Studio попросит вас заключить эту строку в try/catch для всех исключений, создаваемых нашим методом. Так что просто позволь ему это сделать.

Удачного кодирования!

Ответ 3

Самый простой способ, который я нашел, - добавить этот класс и выполнить его из метода onCreate

new NukeSSLCerts().nuke();

Он заставит залп доверять всем сертификатам SSL

Ответ 4

Доверяйте всем SSL-сертификатам: - Вы можете обойти SSL, если хотите протестировать на сервере тестирования. Но не используйте этот код для производства.

public static class NukeSSLCerts {
protected static final String TAG = "NukeSSLCerts";

public static void nuke() {
    try {
        TrustManager[] trustAllCerts = new TrustManager[] { 
            new X509TrustManager() {
                public X509Certificate[] getAcceptedIssuers() {
                    X509Certificate[] myTrustedAnchors = new X509Certificate[0];  
                    return myTrustedAnchors;
                }

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

}

Пожалуйста, вызовите эту функцию в функции onCreate() в Activity или в вашем классе приложений.

NukeSSLCerts.nuke();

Это можно использовать для Volley в Android. Дополнительная ссылка. https://newfivefour.com/android-trust-all-ssl-certificates.html