Reputation: 5149
i try to request a local service with https without certificate check. But i got this execption.
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
here is a part of code:
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());
}
what is wrong here?
Upvotes: 1
Views: 5788
Reputation: 5149
Hy,
i resolved it with this code part:
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());
}
}
and i called this function before i created the RestTemplate.
Upvotes: 1
Reputation: 39261
This problem is due to incomplete trust path for the server certificate: the server certificate is probably not trusted by the client.
Usually the fix is to import the server certificate into the client trust store. The default trustStore is in jre/lib/security/cacerts but is is a better practice to use your own keystore
You can create an SSLSocketFactory
and add to your connection before connecting or apply to all connections using the static method
HttpsURLConnection.setDefaultSSLSocketFactory(sslFactory);
This is an example to create the socket factory
/* 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();
Example of loading the keyStore
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(trustStore, trustStorePassword);
trustStore.close();
The trust store can also be configured using system properties
System.setProperty("javax.net.ssl.trustStore", "pathtoyourjavakeystorefile");
System.setProperty("javax.net.ssl.trustStorePassword", "password");
The simplest way to create the key store file is using the GUI tool Portecle. New KeyStore > Import Trusted certificates
You can import the root certificate of the chain if you want to 'trust' all certificates from root, or import only the server certificate. For a self-signed certificate, import it directly
Upvotes: 1