it-roy-ru.com

Как игнорировать построение пути PKIX не удалось: Sun.security.provider.certpath.SunCertPathBuilderException?

При попытке отправить запрос на http-сервер я получил следующее исключение:

Вот код, который я использовал

URL url = new URL(
        "https://www.abc.com");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();

conn.setRequestMethod("GET");

conn.setDoOutput(true);

DataOutputStream wr = new DataOutputStream(conn.getOutputStream());
// wr.writeBytes(params);
wr.flush();
wr.close();

BufferedReader br = new BufferedReader(new InputStreamReader(
        conn.getInputStream()));
String line = null;
while ((line = br.readLine()) != null) {
    System.out.println(line);
}

Вот исключение:

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
    at com.Sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.Java:174)
    at com.Sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.Java:1731)
    at com.Sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.Java:241)
    at com.Sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.Java:235)
    at com.Sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.Java:1206)
    at com.Sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.Java:136)
    at com.Sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.Java:593)
    at com.Sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.Java:529)
    at com.Sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.Java:925)
    at com.Sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.Java:1170)
    at com.Sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.Java:1197)
    at com.Sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.Java:1181)
    at Sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.Java:434)
    at Sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.Java:166)
    at Sun.net.www.protocol.http.HttpURLConnection.getOutputStream(HttpURLConnection.Java:1014)
    at Sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.Java:230)
    at com.Amazon.mzang.tools.httpchecker.CategoryYank.getPV(CategoryYank.Java:32)
    at com.Amazon.mzang.tools.httpchecker.CategoryYank.main(CategoryYank.Java:18)
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(PKIXValidator.Java:323)
    at Sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.Java:217)
    at Sun.security.validator.Validator.validate(Validator.Java:218)
    at com.Sun.net.ssl.internal.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.Java:126)
    at com.Sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.Java:209)
    at com.Sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.Java:249)
    at com.Sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.Java:1185)
    ... 13 more
Caused by: Sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at Sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.Java:174)
    at Java.security.cert.CertPathBuilder.build(CertPathBuilder.Java:238)
    at Sun.security.validator.PKIXValidator.doBuild(PKIXValidator.Java:318)
    ... 19 more

Сервер не принадлежит мне. Есть ли способ игнорировать это исключение?

58
DeepNightTwo

Если вы хотите полностью игнорировать сертификат, взгляните на ответ здесь: Игнорируйте самоподписанный ssl-сертификат с помощью Jersey Client

Хотя это сделает ваше приложение уязвимым для атак "человек посередине".

Или попробуйте добавить сертификат в ваше хранилище Java в качестве доверенного сертификата. Этот сайт может быть полезным. http://blog.icodejava.com/tag/get-public-key-of-ssl-certificate-in-Java/

Вот еще одна тема, показывающая, как добавить сертификат в ваш магазин. Java SSL connect, программно добавить сертификат сервера в хранилище ключей

Ключ:

KeyStore.Entry newEntry = new KeyStore.TrustedCertificateEntry(someCert);
ks.setEntry("someAlias", newEntry, null);
46
km1

Я использовал приведенный ниже код для отмены проверки SSL в моем проекте, и это сработало для меня.

package com.beingjavaguys.testftp;

import Java.io.InputStreamReader;
import Java.io.Reader;
import Java.net.URL;
import Java.net.URLConnection;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import Java.security.cert.X509Certificate;

/**
 * Fix for 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
 */
public class ConnectToHttpsUrl {
    public static void main(String[] args) throws Exception {
        /* Start of Fix */
        TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
            public Java.security.cert.X509Certificate[] getAcceptedIssuers() { return null; }
            public void checkClientTrusted(X509Certificate[] certs, String authType) { }
            public void checkServerTrusted(X509Certificate[] certs, String authType) { }

        } };

        SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, trustAllCerts, new Java.security.SecureRandom());
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());

        // Create all-trusting Host name verifier
        HostnameVerifier allHostsValid = new HostnameVerifier() {
            public boolean verify(String hostname, SSLSession session) { return true; }
        };
        // Install the all-trusting Host verifier
        HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
        /* End of the fix*/

        URL url = new URL("https://nameofthesecuredurl.com");
        URLConnection con = url.openConnection();
        Reader reader = new InputStreamReader(con.getInputStream());
        while (true) {
            int ch = reader.read();
            if (ch == -1) 
                break;
            System.out.print((char) ch);
        }
    }
}
33
Kishore Kumar

Установите для свойства validateTLSCertificates значение false для вашей команды JSoup .

Jsoup.connect("https://google.com/").validateTLSCertificates(false).get();
15
Zahid Hasan

FWIW, в Ubuntu 10.04.2 LTS установка ca-Certificate-Java и пакетов ca-Certificates исправили эту проблему для меня.

4
slim

Я получил ту же ошибку при выполнении нижеприведенного простого теста spring-boot + RestAssured.

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import static com.jayway.restassured.RestAssured.when;
import static org.Apache.http.HttpStatus.SC_OK;

@RunWith(SpringJUnit4ClassRunner.class)
public class GeneratorTest {

@Test
public void generatorEndPoint() {
    when().get("https://bal-bla-bla-bla.com/generators")
            .then().statusCode(SC_OK);
    }
}

Простое исправление в моем случае - добавить useRelaxedHTTPSValidations ()

RestAssured.useRelaxedHTTPSValidation();

Тогда тест выглядит

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import static com.jayway.restassured.RestAssured.when;
import static org.Apache.http.HttpStatus.SC_OK;

@RunWith(SpringJUnit4ClassRunner.class)
public class GeneratorTest {

@Before
public void setUp() {
   RestAssured.useRelaxedHTTPSValidation();
}


@Test
public void generatorEndPoint() {
    when().get("https://bal-bla-bla-bla.com/generators")
            .then().statusCode(SC_OK);
    }
}
2
Praveen

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

0
Smart Coder