我有一个带HTTPURL连接的java代码,它一直在说错误,如下所示,它表示第47行的错误。
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException:PKIX路径构建失败: sun.security.provider.certpath.SunCertPathBuilderException:无法 找到所请求目标的有效证书路径|
它还在第47行显示错误:OutputStream output = httpURLConnection.getOutputStream();
无法跟踪网址响应代码,您可以自动访问该网址。
这里是堆栈跟踪和javacode
https://gist.github.com/theakathir/c9138e3ea7470b698ec06a7db7dcdeab
感谢有人可以协助解决这个问题。感谢
答案 0 :(得分:2)
服务器的域证书通常由中间证书颁发机构签名,中间证书颁发机构又由根证书颁发机构签名。所有常见的客户端(浏览器 - chrome,mozilla,internet-explorer,safari,opera和java-vm)都有自己的信任存储,并且在安装过程中已经捆绑了证书颁发机构。
例外意味着您指向的服务器的服务器证书尚未由jvm信任的证书颁发机构签名。
在这种情况下,您通常会构建自己的信任管理器,而不是修改jvm的默认信任库(位于$JAVA_HOME\jre\lib\security\cacerts
)。
代码段看起来像这样:
package com.example.so.tls;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory;
/**
* <p> https://stackoverflow.com/q/44607949/2862341 </p>
* @author ravindra
*/
public class TestCustomTruststore {
public static void main(String[] args) {
String pathToTruststore = "/path/to/customTruststore.jks"; // truststore has the server certificate loaded
try {
File file = new File(pathToTruststore);
KeyStore trustStore = KeyStore.getInstance("jks");
trustStore.load(new FileInputStream(file), null);
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("PKIX");
trustManagerFactory.init(trustStore);
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, trustManagerFactory.getTrustManagers(), null);
SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
String urlStr = "https://example.com";
URL url = new URL(urlStr);
HttpsURLConnection httpsURLConnection = (HttpsURLConnection) url.openConnection();
httpsURLConnection.setSSLSocketFactory(sslSocketFactory);
httpsURLConnection.getInputStream();
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (CertificateException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
}
}
}
PS:您需要使用$JAVA_HOME\bin\keytool
实用程序来创建密钥库并加载证书。
答案 1 :(得分:1)
您需要将证书添加到位于%JAVA_HOME%\ lib \ security \ cacerts的已使用JVM的密钥库文件中。
首先,您可以通过运行以下命令来检查您的证书是否已经存在于密钥库中:keytool -list -keystore“%JAVA_HOME%/ jre / lib / security / cacerts”(您无需提供密码)
如果您的证书丢失,可以通过浏览器下载并使用以下命令将其添加到密钥库来获取证书:
keytool -import -noprompt -trustcacerts -alias -file -keystore -storepass
安装导入后,您可以再次运行第一个命令,检查您的证书是否已添加。
答案 2 :(得分:0)
中间替代方案是使用您自己的信任库文件(不是JRE/lib/security/cacerts
甚至是jssecacerts
这是官方备选方案)但不是编写代码来加载此文件并在{{1}中使用它您可以通过设置系统属性SSLSocketFactory
和javax.net.ssl.trustStore
让默认工厂使用您的文件。在许多情况下,这些可以在命令行上设置,以运行您的Java程序,而不需要任何代码更改。
请注意,当今Internet上几乎所有SSL / TLS证书都不是由根CA(位于各种浏览器,客户端和JVM信任库中)直接颁发,而是使用也称为“链”证书的中间CA证书因为它用于从服务器/叶子证书链接到根证书。偶尔会有两个链证书,原则上可以更多。 验证错误可能不是由缺少root的JVM引起的,而是由服务器未能发送链证书引起的;使用浏览器访问时可能不会注意到此错误,因为浏览器有时会使用其他方式获取链证书。在这种情况下,要么手动检查证书链 - 对于java7,您可以使用javax.net.ssl.trustStorePassword
和/或如果您使用openssl使用keytool -printcert -sslserver $host[:$port]
,然后在每个PEM块上使用openssl s_client -connect $host:$port -showcerts
在该输出中 - 或使用像https://www.ssllabs.com/ssltest/