SSLHandshakeException:ValidatorException:PKIX 路径构建失败:sun.security.provider.certpath.SunCertPathBuilderException:
SSLHandshakeException: ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException:
我尝试在没有证书检查的情况下使用 https 请求本地服务。但是我得到了这个例外。
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
这是部分代码:
try {
RestTemplate restTemplate = new RestTemplate();
HttpsURLConnection.setDefaultHostnameVerifier(
(hostname, session) -> hostname.equals("IPADDRESS"));
responseEntity = restTemplate.exchange(url, HttpMethod.POST, httpEntity, String.class);
} catch (HttpClientErrorException e) {
LOGGER.error(e.toString());
}
这里有什么问题?
此问题是由于服务器证书的信任路径不完整造成的:客户端可能不信任服务器证书。
通常的解决方法是将服务器证书导入客户端信任库。默认的 trustStore 在 jre/lib/security/cacerts 中,但更好的做法是使用您自己的密钥库
您可以创建一个 SSLSocketFactory
并在连接之前添加到您的连接,或者使用静态方法应用于所有连接
HttpsURLConnection.setDefaultSSLSocketFactory(sslFactory);
这是创建套接字工厂的示例
/* Load the keyStore that includes the server cert as a "trusted" entry. */
KeyStore keyStore = ...
TrustManagerFactory tmf =
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(keyStore);
SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(null, tmf.getTrustManagers(), null);
sslFactory = ctx.getSocketFactory();
加载keyStore的例子
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(trustStore, trustStorePassword);
trustStore.close();
也可以使用系统属性配置信任库
System.setProperty("javax.net.ssl.trustStore", "pathtoyourjavakeystorefile");
System.setProperty("javax.net.ssl.trustStorePassword", "password");
创建密钥存储文件的最简单方法是使用 GUI 工具 Portecle。 新建密钥库 > 导入可信证书
如果要'trust'所有根证书,可以导入链的根证书,或者只导入服务器证书。自签名证书,直接导入
嗨,
我用这段代码部分解决了它:
private void disableCertificateVerification() {
TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
@Override
public void checkClientTrusted(java.security.cert.X509Certificate[] arg0, String arg1) throws CertificateException {
}
@Override
public void checkServerTrusted(java.security.cert.X509Certificate[] arg0, String arg1)
throws CertificateException {
}
} };
try {
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
HttpsURLConnection.setDefaultHostnameVerifier(
(hostname, session) -> hostname.equals("IPADDRESS"));
} catch (NoSuchAlgorithmException | KeyManagementException e) {
LOGGER.error(e.toString());
}
}
我在创建 RestTemplate 之前调用了这个函数。
我尝试在没有证书检查的情况下使用 https 请求本地服务。但是我得到了这个例外。
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
这是部分代码:
try {
RestTemplate restTemplate = new RestTemplate();
HttpsURLConnection.setDefaultHostnameVerifier(
(hostname, session) -> hostname.equals("IPADDRESS"));
responseEntity = restTemplate.exchange(url, HttpMethod.POST, httpEntity, String.class);
} catch (HttpClientErrorException e) {
LOGGER.error(e.toString());
}
这里有什么问题?
此问题是由于服务器证书的信任路径不完整造成的:客户端可能不信任服务器证书。
通常的解决方法是将服务器证书导入客户端信任库。默认的 trustStore 在 jre/lib/security/cacerts 中,但更好的做法是使用您自己的密钥库
您可以创建一个 SSLSocketFactory
并在连接之前添加到您的连接,或者使用静态方法应用于所有连接
HttpsURLConnection.setDefaultSSLSocketFactory(sslFactory);
这是创建套接字工厂的示例
/* Load the keyStore that includes the server cert as a "trusted" entry. */
KeyStore keyStore = ...
TrustManagerFactory tmf =
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(keyStore);
SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(null, tmf.getTrustManagers(), null);
sslFactory = ctx.getSocketFactory();
加载keyStore的例子
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(trustStore, trustStorePassword);
trustStore.close();
也可以使用系统属性配置信任库
System.setProperty("javax.net.ssl.trustStore", "pathtoyourjavakeystorefile");
System.setProperty("javax.net.ssl.trustStorePassword", "password");
创建密钥存储文件的最简单方法是使用 GUI 工具 Portecle。 新建密钥库 > 导入可信证书
如果要'trust'所有根证书,可以导入链的根证书,或者只导入服务器证书。自签名证书,直接导入
嗨,
我用这段代码部分解决了它:
private void disableCertificateVerification() {
TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
@Override
public void checkClientTrusted(java.security.cert.X509Certificate[] arg0, String arg1) throws CertificateException {
}
@Override
public void checkServerTrusted(java.security.cert.X509Certificate[] arg0, String arg1)
throws CertificateException {
}
} };
try {
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
HttpsURLConnection.setDefaultHostnameVerifier(
(hostname, session) -> hostname.equals("IPADDRESS"));
} catch (NoSuchAlgorithmException | KeyManagementException e) {
LOGGER.error(e.toString());
}
}
我在创建 RestTemplate 之前调用了这个函数。