Разрешение javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: сбой построения пути PKIX Ошибка? - PullRequest
361 голосов
/ 08 марта 2012

Редактировать: - Попытался отформатировать вопрос и принял ответ более презентабельно у меня Блог

Вот оригинальный номер.

Я получаю эту ошибку:

подробное сообщение sun.security.validator.ValidatorException: путь PKIX здание не удалось:
sun.security.provider.certpath.SunCertPathBuilderException: невозможно найти действительный путь сертификации для запрошенной цели

вызывает javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: создание пути PKIX ошибка: sun.security.provider.certpath.SunCertPathBuilderException: невозможно найти действительный путь сертификации для запрошенной цели

Я использую Tomcat 6 в качестве веб-сервера. У меня есть два веб-приложения HTTPS, установленные на разных Tomcats на разных портах, но на одной машине. Скажите App1(port 8443) и App2(port 443). App1 подключается к App2. Когда App1 подключается к App2, я получаю вышеуказанную ошибку. Я знаю, что это очень распространенная ошибка, поэтому сталкивался со многими решениями на разных форумах и сайтах. У меня есть запись ниже в server.xml обоих Tomcats:

keystoreFile="c:/.keystore" 
keystorePass="changeit"

На каждом сайте указывается одна и та же причина, по которой сертификат, предоставленный app2, отсутствует в доверенном хранилище app1 jvm. Кажется, это также верно, когда я пытался перейти по тому же URL-адресу в браузере IE, он работает (с потеплением. Существует проблема с сертификатом безопасности этого веб-сайта. Здесь я говорю, перейдите на этот веб-сайт). Но когда Java-клиент использует тот же URL-адрес (в моем случае), я получаю вышеуказанную ошибку. Поэтому, чтобы положить его в доверенное хранилище, я попробовал эти три варианта:

Option1

System.setProperty("javax.net.ssl.trustStore", "C:/.keystore");
System.setProperty("javax.net.ssl.trustStorePassword", "changeit");

Option2 Установка ниже в переменной среды

CATALINA_OPTS -- param name
-Djavax.net.ssl.trustStore=C:\.keystore -Djavax.net.ssl.trustStorePassword=changeit ---param value

Вариант3 Установка ниже в переменной среды

JAVA_OPTS -- param name
-Djavax.net.ssl.trustStore=C:\.keystore -Djavax.net.ssl.trustStorePassword=changeit ---param value

Но ничего не получалось .

Что наконец-то сработало выполняет подход Java, предложенный в Как обрабатывать недействительные сертификаты SSL с помощью Apache HttpClient? от Pascal Thivent, т.е. выполнение программы InstallCert.

Но этот подход подходит для установки devbox, но я не могу использовать его в производственной среде.

Мне интересно почему три упомянутых выше подхода не сработали, когда я упомянул одинаковые значения в server.xml сервера app2 и одинаковые значения в хранилище доверенных сертификатов, установив

System.setProperty("javax.net.ssl.trustStore", "C:/.keystore") and System.setProperty("javax.net.ssl.trustStorePassword", "changeit");

в программе app1.

Для получения дополнительной информации, как я делаю соединение:

URL url = new URL(urlStr);

URLConnection conn = url.openConnection();

if (conn instanceof HttpsURLConnection) {

  HttpsURLConnection conn1 = (HttpsURLConnection) url.openConnection();

  conn1.setHostnameVerifier(new HostnameVerifier() {
    public boolean verify(String hostname, SSLSession session) {
      return true;
    }
  });

  reply.load(conn1.getInputStream());

Ответы [ 16 ]

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

Необходимо добавить сертификат для App2 в файл склада доверенных сертификатов используемой JVM, расположенный по адресу %JAVA_HOME%\lib\security\cacerts.

Сначала вы можете проверить, находится ли ваш сертификат в доверенном хранилище, выполнив следующую команду: keytool -list -keystore "%JAVA_HOME%/jre/lib/security/cacerts" (вам не нужно указывать пароль)

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

keytool -import -noprompt -trustcacerts -alias <AliasName> -file <certificate> -keystore <KeystoreFile> -storepass <Password>

После импорта вы можете снова запустить первую команду, чтобы проверить, был ли добавлен ваш сертификат.

Информацию о Sun / Oracle можно найти здесь .

162 голосов
/ 21 сентября 2012

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: сбой построения пути PKIX: sun.security.provider.certpath.SunCertPathBuilderException: не удалось найти действительный путь сертификации для запрошенной цели

• Когда я получил сообщение об ошибке, я попытался выяснить значение выражения в Google и обнаружил, что эта проблема возникает, когда сервер меняет свой сертификат HTTPS SSL, а наша старая версия Java не распознает корневой центр сертификации. (CA).

• Если вы можете получить доступ к URL-адресу HTTPS в своем браузере, то можно обновить Java для распознавания корневого CA.

• В браузере перейдите по URL-адресу HTTPS, к которому у Java нет доступа. Нажмите на цепочку сертификатов HTTPS (в Internet Explorer есть значок блокировки), нажмите на замок, чтобы просмотреть сертификат.

• Перейдите в «Детали» сертификата и «Копировать в файл». Скопируйте его в формате Base64 (.cer) . Он будет сохранен на вашем рабочем столе.

• Установите сертификат, игнорируя все предупреждения.

• Так я собрал информацию о сертификате URL-адреса, к которому я пытался получить доступ.

Теперь я должен был сделать свою версию Java известной о сертификате, чтобы в дальнейшем он не отказывался распознавать URL. В связи с этим я должен упомянуть, что, по-моему, информация о корневом сертификате по умолчанию остается в JDK-каталоге \ jre \ lib \ security , а пароль по умолчанию для доступа: changeit.

Для просмотра информации о каскадах необходимо выполнить следующие процедуры:

• Нажмите кнопку Пуск -> Выполнить

• Тип cmd. Откроется командная строка (может потребоваться открыть ее как администратор).

• Перейдите в каталог Java/jreX/bin

• Введите следующее

keytool -list -keystore D: \ Java \ jdk1.5.0_12 \ jre \ lib \ security \ cacerts

Содержит список текущих сертификатов, содержащихся в хранилище ключей. Это выглядит примерно так:

C: \ Documents and Settings \ NeelanjanaG> keytool -list -keystore D: \ Java \ jdk1.5.0_12 \ jre \ lib \ security \ cacerts

Введите пароль хранилища ключей: changeit

Тип хранилища ключей: jks

Поставщик Keystore: SUN

В вашем хранилище ключей содержится 44 записи

verisignclass3g2ca, 26 марта 2004 г., trustCertEntry,

Отпечаток сертификата (MD5): A2: 33: 9B: 4C: 74: 78: 73: D4: 6C: E7: C1: F3: 8D: CB: 5C: E9

entrustclientca, 9 января 2003 г., trustCertEntry,

Отпечаток сертификата (MD5): 0C: 41: 2F: 13: 5B: A0: 54: F5: 96: 66: 2D: 7E: CD: 0E: 03: F4

thawtepersonalbasicca, 13 февраля 1999 г., trustCertEntry,

Отпечаток сертификата (MD5): E6: 0B: D2: C9: CA: 2D: 88: DB: 1A: 71: 0E: 4B: 78: EB: 02: 41

addtrustclass1ca, 1 мая 2006 г., trustCertEntry,

Отпечаток сертификата (MD5): 1E: 42: 95: 02: 33: 92: 6B: B9: 5F: C0: 7F: DA: D6: B2: 4B: FC

verisignclass2g3ca, 26 марта 2004 г., trustCertEntry,

Отпечаток сертификата (MD5): F8: BE: C4: 63: 22: C9: A8: 46: 74: 8B: B8: 1D: 1E: 4A: 2B: F6

• Теперь мне пришлось включить ранее установленный сертификат в cacerts.

• Для этого используется следующая процедура:

keytool –import –noprompt –trustcacerts –alias ALIASNAME -file FILENAME_OF_THE_INSTALLED_CERTIFICATE -keystore PATH_TO_CACERTS_FILE -storepass ПАРОЛЬ

Если вы используете Java 7:

keytool –importcert –trustcacerts –alias ALIASNAME -file PATH_TO_FILENAME_OF_THE_INSTALLED_CERTIFICATE -keystore PATH_TO_CACERTS_FILE -storepass changeit

• Затем он добавит информацию о сертификате в файл cacert.

Это решение, которое я нашел для упомянутого выше исключения !!

32 голосов
/ 18 августа 2015

Как работает - это в Tomcat 7

Я хотел поддержать самозаверяющий сертификат в приложении Tomcat, но следующий фрагмент не работал

import java.io.DataOutputStream;
import java.net.HttpURLConnection;
import java.net.URL;

public class HTTPSPlayground {
    public static void main(String[] args) throws Exception {

        URL url = new URL("https:// ... .com");
        HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();

        httpURLConnection.setRequestMethod("POST");
        httpURLConnection.setRequestProperty("Accept-Language", "en-US,en;q=0.5");
        httpURLConnection.setDoOutput(true);
        DataOutputStream wr = new DataOutputStream(httpURLConnection.getOutputStream());

        String serializedMessage = "{}";
        wr.writeBytes(serializedMessage);
        wr.flush();
        wr.close();

        int responseCode = httpURLConnection.getResponseCode();
        System.out.println(responseCode);
    }
}

вот что решило мою проблему:

1) Загрузить файл .crt

echo -n | openssl s_client -connect <your domain>:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > ~/<your domain>.crt
  • замените <your domain> своим доменом (например, jossef.com)

2) Применить файл .crt в хранилище сертификатов Java cacerts

keytool -import -v -trustcacerts -alias <your domain> -file ~/<your domain>.crt -keystore <JAVA HOME>/jre/lib/security/cacerts -keypass changeit -storepass changeit
  • замените <your domain> своим доменом (например, jossef.com)
  • замените <JAVA HOME> своим домашним каталогом java

3) Взломать

Несмотря на то, что iv'e установил мой сертификат в Java хранилищах сертификатов по умолчанию, Tomcat игнорирует это (похоже, он не настроен на использование хранилищ сертификатов по умолчанию Java).

Чтобы взломать это, добавьте в ваш код следующее:

String certificatesTrustStorePath = "<JAVA HOME>/jre/lib/security/cacerts";
System.setProperty("javax.net.ssl.trustStore", certificatesTrustStorePath);

// ...
6 голосов
/ 25 сентября 2018

В моем случае проблема заключалась в том, что веб-сервер отправлял только сертификат и промежуточный ЦС, а не корневой ЦС.Добавление этой опции JVM решило проблему: -Dcom.sun.security.enableAIAcaIssuers=true

Доступна поддержка метода доступа caIssuers для расширения доступа к информации о полномочиях.По умолчанию он отключен для совместимости и его можно включить, установив системное свойство com.sun.security.enableAIAcaIssuers в значение true.

Если установлено значение true, реализация CertPathBuilder в PKIX от Sun использует информацию в расширении AIA сертификата (вдополнение к указанному CertStores) для поиска сертификата выдающего ЦС, при условии, что это URI типа ldap, http или ftp.

Источник

5 голосов
/ 23 декабря 2017

Другой причиной может быть устаревшая версия JDK. Я использовал jdk версии 1.8.0_60, просто обновление до последней версии решило проблему с сертификатом.

5 голосов
/ 27 июля 2013

Мой файл cacerts был полностью пуст. Я решил эту проблему, скопировав файл cacerts с моего компьютера с Windows (который использует Oracle Java 7) и скопировал его в мой Linux-пакет (OpenJDK).

cd %JAVA_HOME%/jre/lib/security/
scp cacerts mylinuxmachin:/tmp

и затем на машине linux

cp /tmp/cacerts /etc/ssl/certs/java/cacerts

Пока все отлично работает.

4 голосов
/ 25 июля 2018

Я использовал jdk1.8.0_171, когда столкнулся с той же проблемой. Я попробовал два лучших решения здесь (добавление сертификата с помощью keytool и другого решения, в котором есть хак), но они не сработали для меня.

Я обновил свой JDK до 1.8.0_181, и он заработал как шарм.

4 голосов
/ 11 мая 2018

Ниже у меня работает код:

import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.X509TrustManager;

public class TrustAnyTrustManager implements X509TrustManager {

public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}

public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}

public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[] {};
}
}

HttpsURLConnection conn = null;
            URL url = new URL(serviceUrl);
            conn = (HttpsURLConnection) url.openConnection();
             SSLContext sc = SSLContext.getInstance("SSL");  
             sc.init(null, new TrustManager[]{new TrustAnyTrustManager()}, new java.security.SecureRandom());  

             conn.setSSLSocketFactory(sc.getSocketFactory());
4 голосов
/ 23 апреля 2017

Для меня эта ошибка также возникла при попытке подключиться к процессу за обратным прокси-сервером NGINX, который обрабатывал SSL.

Оказалось, что проблема в сертификате без объединения всей цепочки сертификатов.Когда я добавил промежуточные сертификаты, проблема была решена.

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

4 голосов
/ 06 марта 2017

Используя Tomcat 7 под Linux, это помогло.

String certificatesTrustStorePath = "/etc/alternatives/jre/lib/security/cacerts";
System.setProperty("javax.net.ssl.trustStore", certificatesTrustStorePath);
System.setProperty("javax.net.ssl.trustStorePassword", "changeit");

Под Linux $JAVA_HOME не всегда настраивается, но обычно /etc/alternatives/jre указывает на $JAVA_HOME/jre

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