Java кеширует сбои SSL - можно ли как-то их сбросить - PullRequest
0 голосов
/ 13 февраля 2019

Я пытаюсь протестировать свою реализацию SSL в модульных тестах, и у меня есть один сценарий, который я не совсем понимаю.

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

Вот мой код, сервер и клиент работают локально.Я использую один JKS-файл для trustStore и keyStore.Ошибка возникает независимо от того, какая была первоначальная ошибка, в следующий раз я всегда получу первую ошибку.

Если я не выполню первый запрос, то работает второй.

Есливам интересно, какой здесь вариант использования, у нас есть несколько локальных серверов, которые используют сертификаты https от внутренней PKI, когда кто-то неправильно настраивает сервер или сертификат, мы бы хотели иметь возможность их явно изменить, не выключаявся ВМ.

    //attempt a connection without certificates, will fail
    try (final InputStream stream = new URL("https://localhost:" + port).openStream()){
        System.out.println(IOUtils.toString(stream, Charset.defaultCharset()));
    } catch (IOException e){
        System.out.println("Failed to load: " + StackTraceUtil.getStackTrace(e));
    }

    //copies the jks file to a temporary location
    final File jksFile = copyJKSFile();

    //ignore host names, running locally, won't use this in production
    HttpsURLConnection.setDefaultHostnameVerifier((hostname, sslSession) -> hostname.equalsIgnoreCase("localhost"));

    //set the system properties
    System.setProperty("javax.net.ssl.keyStore", jksFile.getAbsolutePath());
    System.setProperty("javax.net.ssl.keyStorePassword", password);
    System.setProperty("javax.net.ssl.trustStore", jksFile.getAbsolutePath());
    System.setProperty("javax.net.ssl.trustStorePassword", password);

    //this should work now
    try (final InputStream stream = new URL("https://localhost:" + port).openStream()){
        System.out.println(IOUtils.toString(stream, Charset.defaultCharset()));
    } catch (IOException e){
        System.out.println("Failed to load: " + StackTraceUtil.getStackTrace(e));
    }

Спасибо за любую помощь!

1 Ответ

0 голосов
/ 19 февраля 2019

Итак, я нашел решение и решил поделиться им на тот случай, если кто-то еще столкнется с этой проблемой.

Класс javax.net.ssl.HttpsURLConnection использует javax.net.ssl.SSLSocketFactory для загрузки ключа иTrustStore, который использует javax.net.ssl.SSLContext внутри.Когда вы ничего не перезаписываете, он использует реализацию по умолчанию, которая загружает файлы и не может быть сброшена после загрузки.

Так что я сделал не для использования реализации по умолчанию, а для установки своей собственнойSSLContext, когда я знал, что файлы изменятся.

final SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
sslContext.init(null, null, null);
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());

Если вы хотите использовать более старые версии TLS, полный список должен быть здесь

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