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
サーバーは私が所有していません。この例外を無視する方法はありますか?
すべて一緒に証明書を無視したい場合は、次の答えを見てください: Jersey Clientを使用して自己署名SSL証明書を無視する
ただし、これによりアプリは中間者攻撃に対して脆弱になります。
または、証明書を信頼できる証明書としてJavaストアに追加してみてください。このサイトは役に立つかもしれません。 http://blog.icodejava.com/tag/get-public-key-of-ssl-certificate-in-Java/
ここに、ストアに証明書を追加する方法を示す別のスレッドがあります。 Java SSL接続、プログラムでサーバー証明書をキーストアに追加
キーは次のとおりです。
KeyStore.Entry newEntry = new KeyStore.TrustedCertificateEntry(someCert);
ks.setEntry("someAlias", newEntry, null);
以下のコードを使用して、プロジェクトの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);
}
}
}
JSoup コマンドのvalidateTLSCertificates
プロパティをfalse
に設定します。
Jsoup.connect("https://google.com/").validateTLSCertificates(false).get();
FWIW、Ubuntu 10.04.2 LTSでca-certificates-Javaおよびca-certificatesパッケージをインストールすると、この問題が修正されました。
以下の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);
}
}
CloudFoundryを使用している場合、証明書を含むキーストアとともにjarを明示的にプッシュする必要があります。