Теперь, когда SSLSocketFactory устарела на Android, как лучше всего обрабатывать аутентификацию клиентского сертификата?

Я работаю над приложением для Android, для которого требуется проверка подлинности сертификата клиента (с файлами PKCS 12). После устаревания всего, что apache.http.*, мы начали довольно большую работу по рефакторингу нашего сетевого уровня, и мы решили пойти с OkHttp в качестве замены, и пока мне это очень нравится.

Однако я не нашел другого способа обработки аутентификации сертификата клиента без использования SSLSocketFactory, с OkHttp или чем-либо еще в этом отношении. Итак, как лучше поступить в данном конкретном случае? Есть ли другой способ с OkHttp для обработки такой аутентификации?


person TheYann    schedule 23.06.2015    source источник
comment
SSLSocketFactory не считается устаревшим ни в текущих поставляемых версиях Android или в M Developer Preview.   -  person CommonsWare    schedule 23.06.2015
comment
Боже мой, вы абсолютно правы, я никогда не осознавал, что существует 2 класса SSLSocketFactory! org.apache.http.conn.ssl.SSLSocketFactory устарел, а javax.net.ssl.SSLSocketFactory — нет! Большое спасибо за это просвещение.   -  person TheYann    schedule 23.06.2015
comment
И наоборот, я не осознавал, что у HttpClient есть собственный класс SSLSocketFactory. :-)   -  person CommonsWare    schedule 23.06.2015


Ответы (3)


Судя по всему, есть два класса SSLSocketFactory. HttpClient имеет свой собственный, и он устарел вместе с остальной частью HttpClient. Однако все остальные будут использовать более обычную javax.net.ssl версию SSLSocketFactory, которая не устарело (спасибо $DEITY).

person CommonsWare    schedule 23.06.2015

если вы используете https, вы должны использовать действительный сертификат. Как на этапе разработки вы должны доверять сертификату? sslSocketFactory(SSLSocketFactory sslSocketFactory) устарел и заменен на sslSocketFactory(SSLSocketFactory sslSocketFactory, X509TrustManager trustManager), вам необходимо обновить файл gradle. Фрагмент кода ниже поможет вам получить доверенный OkHttpClient, который доверяет любому сертификату ssl.

TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init((KeyStore) null);
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
    throw new IllegalStateException("Unexpected default trust managers:" + Arrays.toString(trustManagers));
}
X509TrustManager trustManager = (X509TrustManager) trustManagers[0];
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, new TrustManager[] { trustManager }, null);
SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
OkHttpClient client = new OkHttpClient.Builder().sslSocketFactory(sslSocketFactory, trustManager);
person user2167877    schedule 29.11.2016
comment
Спасибо, устаревшее предупреждение удаляется простым добавлением диспетчера доверия. - person tryp; 20.02.2017
comment
Я по-прежнему получаю SSLHandshakeException: соединение закрыто узлом - person IgorGanapolsky; 13.06.2018
comment
Я не эксперт в NTLM, но может вам понадобится использовать внешнюю библиотеку в качестве JCIFS. - person user2167877; 14.06.2018

Посмотрите, я нашел какое-то решение, и на моей стороне все работает хорошо. Проверьте, как я интегрировал ..

OkHttpClient.Builder client = new OkHttpClient.Builder();

добавьте сюда все свойства для экземпляра клиента

. . .

и добавьте эту строку кода для sslSocketFactory:

 try {
        // Create a trust manager that does not validate certificate chains
        final TrustManager[] trustAllCerts = new TrustManager[]{
                new X509TrustManager() {
                    @Override
                    public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) {
                    }

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

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

        // Install the all-trusting trust manager
        final SSLContext sslContext = SSLContext.getInstance("SSL");
        sslContext.init(null, trustAllCerts, new java.security.SecureRandom());

        // Create an ssl socket factory with our all-trusting manager
        final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();

        client.sslSocketFactory(sslSocketFactory, (X509TrustManager) trustAllCerts[0]);
        client.hostnameVerifier((hostname, session) -> true);
    } catch (Exception e) {
        throw new RuntimeException(e);
  }
person Krste Moskov    schedule 07.11.2018
comment
Доверять каждому сертификату и имени хоста — плохая идея. - person bompf; 09.04.2019
comment
Дыра в безопасности! это не рекомендуется - person Jorgesys; 28.01.2020