Вопрос-ответ

Resolving javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed Error?

Устранение исключения javax.net.ssl.SSLHandshakeException: sun.security.validator.Исключение ValidatorException: ошибка при построении пути PKIX?

Редактировать : Я попытался отформатировать вопрос и принятый ответ более презентабельным образом в своем блоге.

Вот исходная проблема.

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


подробное сообщение 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 (порт 8443) и App2 (порт 443). App1 подключается к App2. Когда App1 подключается к App2, я получаю указанную выше ошибку. Я знаю, что это очень распространенная ошибка, поэтому сталкивался со многими решениями на разных форумах и сайтах. У меня есть приведенная ниже запись в server.xml обоих Tomcats:

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

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

Вариант 1

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

Вариант 2

Настройка ниже в переменной окружения

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 и те же значения в truststore, установив

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());
Переведено автоматически
Ответ 1

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

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

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

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

Пример:

keytool -import -noprompt -trustcacerts -alias myFancyAlias -file /path/to/my/cert/myCert.cer -keystore /path/to/my/jdk/jre/lib/security/cacerts/keystore.jks -storepass changeit

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

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

Ответ 2

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


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

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

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

• Перейдите в раздел “Сведения” о сертификате и “Скопируйте в файл". Скопируйте его в формате Base64 (.cer). Он будет сохранен на вашем рабочем столе.

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

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

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

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

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

• Введите 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

Enter keystore password: changeit

Keystore type: jks

Keystore provider: SUN

Your keystore contains 44 entries

verisignclass3g2ca, Mar 26, 2004, trustedCertEntry,

Certificate fingerprint (MD5): A2:33:9B:4C:74:78:73:D4:6C:E7:C1:F3:8D:CB:5C:E9

entrustclientca, Jan 9, 2003, trustedCertEntry,

Certificate fingerprint (MD5): 0C:41:2F:13:5B:A0:54:F5:96:66:2D:7E:CD:0E:03:F4

thawtepersonalbasicca, Feb 13, 1999, trustedCertEntry,

Certificate fingerprint (MD5): E6:0B:D2:C9:CA:2D:88:DB:1A:71:0E:4B:78:EB:02:41

addtrustclass1ca, May 1, 2006, trustedCertEntry,

Certificate fingerprint (MD5): 1E:42:95:02:33:92:6B:B9:5F:C0:7F:DA:D6:B2:4B:FC

verisignclass2g3ca, Mar 26, 2004, trustedCertEntry,

Certificate fingerprint (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 PASSWORD

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

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

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

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

Ответ 3

Как это работает в 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 файл в cacerts хранилище сертификатов Java

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);

// ...
Ответ 4

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


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


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


Источник

java