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

Java: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

Java: исключение sun.security.provider.certpath.Исключение SunCertPathBuilderException: не удается найти действительный путь сертификации к запрошенной цели

У меня есть класс, который загружает файл с https сервера. Когда я запускаю его, он возвращает множество ошибок. Похоже, у меня проблема с моим сертификатом. Можно ли игнорировать аутентификацию клиент-сервер? Если да, то каким образом?

package com.da;

import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.CharBuffer;
import java.util.concurrent.Future;

import org.apache.http.HttpResponse;
import org.apache.http.client.utils.URIUtils;
import org.apache.http.impl.nio.client.DefaultHttpAsyncClient;
import org.apache.http.nio.IOControl;
import org.apache.http.nio.client.HttpAsyncClient;
import org.apache.http.nio.client.methods.AsyncCharConsumer;
import org.apache.http.nio.client.methods.HttpAsyncGet;
import org.apache.http.nio.client.methods.HttpAsyncPost;

public class RSDDownloadFile {
static FileOutputStream fos;

public void DownloadFile(String URI, String Request) throws Exception
{
java.net.URI uri = URIUtils.createURI("https", "176.66.3.69:6443", -1, "download.aspx",
"Lang=EN&AuthToken=package", null);
System.out.println("URI Query: " + uri.toString());

HttpAsyncClient httpclient = new DefaultHttpAsyncClient();
httpclient.start();
try {
Future<Boolean> future = httpclient.execute(
new HttpAsyncGet(uri),
new ResponseCallback(), null);

Boolean result = future.get();
if (result != null && result.booleanValue()) {
System.out.println("\nRequest successfully executed");
} else {
System.out.println("Request failed");
}
}
catch(Exception e){
System.out.println("[DownloadFile] Exception: " + e.getMessage());
}
finally {
System.out.println("Shutting down");
httpclient.shutdown();
}
System.out.println("Done");

}

static class ResponseCallback extends AsyncCharConsumer<Boolean> {

@Override
protected void onResponseReceived(final HttpResponse response) {
System.out.println("Response: " + response.getStatusLine());
System.out.println("Header: " + response.toString());
try {
//if(response.getStatusLine().getStatusCode()==200)
fos = new FileOutputStream( "Response.html" );
}catch(Exception e){
System.out.println("[onResponseReceived] Exception: " + e.getMessage());
}
}

@Override
protected void onCharReceived(final CharBuffer buf, final IOControl ioctrl) throws IOException {
try
{
while (buf.hasRemaining())
{
//System.out.print(buf.get());
fos.write(buf.get());
}
}catch(Exception e)
{
System.out.println("[onCharReceived] Exception: " + e.getMessage());
}
}

@Override
protected void onCleanup() {
try
{
if(fos!=null)
fos.close();
}catch(Exception e){
System.out.println("[onCleanup] Exception: " + e.getMessage());
}
System.out.println("onCleanup()");
}

@Override
protected Boolean buildResult() {
return Boolean.TRUE;
}

}
}

Ошибки:

URI Query: https://176.66.3.69:6443/download.aspx?Lang=EN&AuthToken=package
Aug 2, 2011 3:47:57 PM org.apache.http.impl.nio.client.NHttpClientProtocolHandler exception
SEVERE: I/O error: General SSLEngine problem
javax.net.ssl.SSLHandshakeException: General SSLEngine problem
at com.sun.net.ssl.internal.ssl.Handshaker.checkThrown(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLEngineImpl.checkTaskThrown(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLEngineImpl.writeAppRecord(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLEngineImpl.wrap(Unknown Source)
at javax.net.ssl.SSLEngine.wrap(Unknown Source)
at org.apache.http.impl.nio.reactor.SSLIOSession.doHandshake(SSLIOSession.java:154)
at org.apache.http.impl.nio.reactor.SSLIOSession.isAppInputReady(SSLIOSession.java:276)
at org.apache.http.impl.nio.client.InternalClientEventDispatch.inputReady(InternalClientEventDispatch.java:79)
at org.apache.http.impl.nio.reactor.BaseIOReactor.readable(BaseIOReactor.java:161)
at org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvent(AbstractIOReactor.java:335)
at org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvents(AbstractIOReactor.java:315)
at org.apache.http.impl.nio.reactor.AbstractIOReactor.execute(AbstractIOReactor.java:275)
at org.apache.http.impl.nio.reactor.BaseIOReactor.execute(BaseIOReactor.java:104)
at org.apache.http.impl.nio.reactor.AbstractMultiworkerIOReactor$Worker.run(AbstractMultiworkerIOReactor.java:542)
at java.lang.Thread.run(Unknown Source)
Caused by: javax.net.ssl.SSLHandshakeException: General SSLEngine problem
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLEngineImpl.fatal(Unknown Source)
at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Unknown Source)
at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Unknown Source)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(Unknown Source)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(Unknown Source)
at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Unknown Source)
at com.sun.net.ssl.internal.ssl.Handshaker$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.net.ssl.internal.ssl.Handshaker$DelegatedTask.run(Unknown Source)
at org.apache.http.impl.nio.reactor.SSLIOSession.doHandshake(SSLIOSession.java:180)
... 9 more
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.validator.PKIXValidator.doBuild(Unknown Source)
at sun.security.validator.PKIXValidator.engineValidate(Unknown Source)
at sun.security.validator.Validator.validate(Unknown Source)
at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(Unknown Source)
at com.sun.net.ssl.internal.ssl.JsseX509TrustManager.checkServerTrusted(Unknown Source)
... 16 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(Unknown Source)
at java.security.cert.CertPathBuilder.build(Unknown Source)
... 21 more
onCleanup()

[DownloadFile] Exception: javax.net.ssl.SSLHandshakeException: General SSLEngine problem
Shutting down
Done
Переведено автоматически
Ответ 1

Проблема возникает, когда на вашем сервере установлен самозаверяющий сертификат. Чтобы обойти это, вы можете добавить этот сертификат в список доверенных сертификатов вашей виртуальной машины.

В этой статье автор описывает, как получить сертификат из вашего браузера и добавить его в файл cacerts вашей виртуальной машины. Вы можете либо отредактировать JAVA_HOME/jre/lib/security/cacerts файл, либо запустить приложение с -Djavax.net.ssl.trustStore параметром. Также проверьте, какой JDK / JRE вы используете, поскольку это часто является источником путаницы.

Смотрите также: Как разрешаются имена серверов SSL-сертификатов / Могу ли я добавить альтернативные имена с помощью keytool? Если вы столкнетесь с java.security.cert.CertificateException: No name matching localhost found исключением.

Ответ 2

Вот что у меня надежно работает на macOS. Обязательно замените example.com и 443 на фактическое имя хоста и порт, к которому вы пытаетесь подключиться, и укажите пользовательский псевдоним. Первая команда загружает предоставленный сертификат с удаленного сервера и сохраняет его локально в формате x509. Вторая команда загружает сохраненный сертификат в хранилище доверия SSL Java.

openssl x509 -in <(openssl s_client -connect example.com:443 -prexit 2>/dev/null) -out ~/example.crt
sudo keytool -importcert -file ~/example.crt -alias example -keystore $(/usr/libexec/java_home)/jre/lib/security/cacerts -storepass changeit

В Windows через Git Bash или WSL первая команда выглядит немного иначе :

openssl s_client -connect git.css.ch:443  -prexit > ~/cert.txt
openssl x509 -in ~/cert.txt -out ~/example.crt
Ответ 3

  1. Экспортируйте SSL-сертификат с помощью Firefox. Вы можете экспортировать его, нажав URL-адрес в браузере, а затем выберите опцию экспорта сертификата. Предположим, что имя файла сертификата - это your.ssl.server.name.crt

  2. Перейдите на свой JRE_HOME/bin или JDK/JRE/bin

  3. Введите команду

  4. keytool -keystore ..\lib\security\cacerts -import -alias your.ssl.server.name -file .\relative-path-to-cert-file\your.ssl.server.name.crt

  5. Перезапустите Java-процесс

Ответ 4

У меня была такая же проблема с действительным подписанным шаблонным сертификатом от symantec.

Сначала попробуйте запустить свое java-приложение с -Djavax.net.debug= SSL, чтобы увидеть, что происходит на самом деле.

В итоге я импортировал промежуточный сертификат, что приводило к разрыву цепочки сертификатов.

Я загрузил отсутствующий промежуточный сертификат от symantec (вы можете увидеть ссылку для скачивания отсутствующего сертификата в журнале подтверждения ssl: http://svrintl-g3-aia.verisign.com/SVRIntlG3.cer в моем случае).

И я импортировал сертификат в хранилище ключей java. После импорта промежуточного сертификата мой подстановочный ssl-сертификат, наконец, начал работать:

keytool -import -keystore ../jre/lib/security/cacerts -trustcacerts -alias "VeriSign Class 3 International Server CA - G3" -file /pathto/SVRIntlG3.cer
java