Как сохранить ненадежный/самозаверяющий сертификат для будущих подключений

Используя HttpsUrlConnection на Android, если я подключаюсь к серверу с ненадежным сертификатом, скорее всего, самозаверяющим, я получаю сообщение об ошибке. Например, когда что-то подобное происходит в браузере, я все равно получаю возможность принять этот сертификат.

  1. План состоит в том, чтобы запустить соединение URL как обычно.
  2. Если возникает ошибка сертификата, повторно запустите его с параметрами Dummy «доверять всем», при этом, конечно, все еще разрывая соединение, как только сертификаты будут получены (в X509TrustManager, а затем в HostNameVerifier). Возврат false в HostNameVerifier отлично справляется с этой задачей.
  3. Спросите пользователя, действительно ли он хочет использовать этот сертификат.

Теперь, как мне добавить этот сертификат в хранилище приложений, чтобы его можно было использовать при следующем подключении к этому серверу?

Или мне нужно приготовить свой собственный X509TrustManager/HostNameVerifier и сравнить входящие данные сертификата с сохраненными, сохраняя при этом нормальную работу для всех сертификатов, подписанных CA.

Другими словами.

  1. Получить публичный сертификат с сервера (сделано)
  2. Спросите пользователя, хотят ли они его использовать.
  3. ИМПОРТируйте этот общедоступный сертификат в собственное хранилище приложения для использования в будущих подключениях.
  4. откат к обычной цепочке доверия для всех доверенных сертификатов ЦС.

Потому что я видел это со всеми другими вопросами, задающими что-то подобное этому, когда люди начинают предлагать все неправильные решения. Мне НЕ нужен AcceptAllVerifier. Я НЕ могу использовать что-либо, что требует импорта сертификата вручную.


person A.Grandt    schedule 04.10.2015    source источник


Ответы (1)


Если я правильно понимаю вашу проблему, вам не нужно AcceptAllVerifier, как в вашем вопросе.

Следующий код является примером, я думаю, вы можете сослаться:

Предположим, что ваше серверное приложение размещается на сервере, который имеет сертификат сервера, в котором "Выдан", например, "localhost". Затем внутри метода verify вы можете проверить «localhost».

     HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
     urlConnection.setSSLSocketFactory(getSSLSocketFactory());
     urlConnection.setHostnameVerifier(new HostnameVerifier() {
               @Override
                    public boolean verify(String hostname, SSLSession session) {
                        HostnameVerifier hv = HttpsURLConnection.getDefaultHostnameVerifier();
                        return hv.verify("localhost", session);
                    }
                });

Подробнее о файле сертификата, getSSLSocketFactory... вы можете обратиться к следующим вопросам (конечно, они могут быть применены для HttpsUrlConnection):

Поддерживает ли Android Volley SSL?

Volley SSL — имя хоста не проверено

Надеюсь это поможет!

person BNK    schedule 05.10.2015
comment
Вам также понадобится TrustManager. На данный момент я играю с пользовательским X509TrustManager, использующим системное хранилище ключей, и с другим пользовательским X509TrustManager внутри него, используя мое собственное хранилище ключей, в методах проверки я затем ловлю ошибку, если глобальное хранилище ключей не может проверить, а затем вызываю внутреннее тестирование TrustManager против моего собственного KeyStore. Если это не удается, соединение ненадежное, и я могу вытащить полученную цепочку сертификатов из пользовательского TrustManager и спросить пользователя, добавив сертификаты в свое собственное хранилище ключей. - person A.Grandt; 05.10.2015
comment
Извините, я мало что понимаю в вашем комментарии. Похоже, у вас уже было собственное решение, что вы ищете в своем вопросе? - person BNK; 05.10.2015