Исключение при печати сведений о сертификате сервера - PullRequest
5 голосов
/ 05 марта 2012

Я установил соединение https между сервером и клиентом, где клиент - это программа Java, а сервер - сервлет.Я использовал следующий код для печати сведений о сертификате с сервера.

URL url = new URL("https://localhost:8443/cert");
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
connection.setSSLSocketFactory(sslsocketfactory);

connection.setDoOutput(true);
if(connection!=null){
    Certificate[] certs = connection.getServerCertificates();// #1 

    System.out.println("Cert Type : " + certs[0].getType());
    System.out.println("Cert Hash Code : " + certs[0].hashCode());
    System.out.println("Cert Public Key Algorithm : " + certs[0].getPublicKey().getAlgorithm());
    System.out.println("Cert Public Key Format : " + certs[0].getPublicKey().getFormat());
    System.out.println("\n");
}

Но я получаю следующее исключение.

java.lang.IllegalStateException: connection not yet open

Я думал, что рукопожатие должно иметь местокак только вызывается метод theurl.openconnection ().В чем здесь проблема?
Исключением является выброшенная строка с номером '# 1' (см. Комментарии в коде выше)

Ответы [ 2 ]

3 голосов
/ 09 марта 2012

Рукопожатие SSLSocket " [...] может быть инициировано одним из трех способов: "

  • вызов startHandshake, который явно начинает рукопожатие, либо
  • любая попытка чтения или записи данных приложения на этом сокете вызывает неявное рукопожатие, либо
  • вызов getSession пытается установить сеанс, если естьв настоящее время нет действительного сеанса, и неявное рукопожатие выполнено.

Кажется, что единственный способ, применяемый через HttpsURLConnection, - это попытаться что-то прочитать / записать (поскольку вы не можетеудерживайте базовый экземпляр SSLSocket непосредственно, чтобы запустить рукопожатие или получить сеанс).

Если вы просто позвоните connection.getInputStream();, прежде чем пытаться получить сертификат, это должно инициировать рукопожатие, и вы получитесертификаты впоследствии.

Обратите внимание, что вы достигнете этой точки только в том случае, если сертификат, который вы хотите просмотреть, пользуется доверием SSLContext / SSLSocketFactory.Для этого вы можете создать хранилище ключей (которое вы будете использовать в качестве хранилища доверенных сертификатов) , которое содержит этот сертификат, как описано в этого ответа .Вы можете использовать if из своего собственного SSLContext или использовать его глобально через системные свойства javax.net.ssl.trustStore* (которые должны быть установлены перед любым использованием SSL. Избегайте примеров TrustManagers, которые ничего не проверяют (здесь есть несколько на SO): он просто полностью отключит проверку сертификата, делая соединение потенциально уязвимым для атак MITM.

3 голосов
/ 08 марта 2012

вы пытаетесь подключиться к самозаверяющему узлу сертификата.Следуйте инструкциям для варианта 2 ответа из этого ответа , который должен позволить вам подключиться.

Я заменил connection.setDoOutput() на connection.connect(), и код работал правильно для меня.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...