Модуль, який я додаю до нашого великого додатку Java, повинен спілкуватися з захищеним SSL веб-сайтом іншої компанії. Проблема полягає в тому, що сайт використовує сертифікат самопідписання. У мене є копія сертифіката, щоб підтвердити, що я не стикаюся з атакою "людина-посеред", і мені потрібно включити цей сертифікат у наш код таким чином, щоб з'єднання з сервером було успішним.
Ось основний код:
void sendRequest(String dataPacket) {
String urlStr = "https://host.example.com/";
URL url = new URL(urlStr);
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
conn.setMethod("POST");
conn.setRequestProperty("Content-Length", data.length());
conn.setDoOutput(true);
OutputStreamWriter o = new OutputStreamWriter(conn.getOutputStream());
o.write(data);
o.flush();
}
Без будь-яких додаткових обробок для самопідписаного сертифіката, це помирає у conn.getOutputStream () за винятком:
Exception in thread "main" javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
....
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
....
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
В ідеалі мій код повинен навчити Java приймати цей самопідписаний сертифікат, для цього місця в додатку та більше ніде.
Я знаю, що я можу імпортувати сертифікат у сховище сертифікатів JRE, і це дозволить Java прийняти його. Це не підхід, який я хочу використовувати, якщо я можу допомогти; на всіх машинах нашого замовника здається дуже інвазивним для одного модуля, який вони можуть не використовувати; це вплине на всі інші програми Java, що використовують той самий JRE, і мені це не подобається, хоча шанси будь-якого іншого додатка Java, що коли-небудь отримує доступ до цього сайту, нульові. Це також не тривіальна операція: в UNIX я повинен отримати права доступу, щоб змінити JRE таким чином.
Я також бачив, що я можу створити екземпляр TrustManager, який здійснює деяку спеціальну перевірку. Схоже, я навіть зможу створити TrustManager, який делегує справжньому TrustManager у всіх випадках, крім цього одного сертифіката. Але схоже, що TrustManager встановлюється в усьому світі, і я вважаю, що це вплине на всі інші з'єднання нашого додатку, і це не пахне мені цілком правильно.
Який переважний, стандартний чи найкращий спосіб налаштувати програму Java для прийняття сертифіката, який підписав самостійно? Чи можу я виконати всі цілі, які я маю на увазі вище, або мені доведеться піти на компроміс? Чи є опція, що включає файли та каталоги та налаштування конфігурації та малопотрібний код?