I'm using restTemplate to request post with SSL. The problem is that I cannot send post request to a server over SSL. I am using a self-signed certificate for the communication. STRANGELY, however, when I send get request over SSL, it is working fine.
I cannot get why POST isn't working unlike GET. Here is my GET and POST using restTemplate.
public <T> T getByRestTemplate(String url, Object param, boolean isSSL, String token, ParameterizedTypeReference<T> responseType) throws RestClientException {
HttpEntity<Object> requestEntity = makeHttpEntity(param, token);
RestTemplate restTemplate = buildRestTemplate(isSSL);
ResponseEntity<T> responseEntity;
responseEntity = restTemplate.exchange(url, HttpMethod.GET, requestEntity, responseType);
return responseEntity.getBody();
}
public <T> T postByRestTemplate(String url, Object param, boolean isSSL, String token, Class<T> responseType) throws RestClientException {
HttpEntity<Object> requestEntity = makeHttpEntity(param, token);
RestTemplate restTemplate = prepareRestTemplate(isSSL);
ResponseEntity<T> responseEntity;
responseEntity = restTemplate.exchange(url, HttpMethod.POST, requestEntity, responseType);
return responseEntity.getBody();
}
private RestTemplate prepareRestTemplate(boolean isSSL){
int connectTimeOut = (appConfigProperties.getConnectTimeOut()!=0)?appConfigProperties.getConnectTimeOut():5000;
int readTimeOut = (appConfigProperties.getReadTimeOut()!=0)?appConfigProperties.getConnectTimeOut():5000;
RestTemplate restTemplate = buildRestTemplate(isSSL);
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
requestFactory.setConnectTimeout(connectTimeOut);
requestFactory.setReadTimeout(readTimeOut);
restTemplate.setRequestFactory(requestFactory);
return restTemplate;
}
private RestTemplate buildRestTemplate(boolean isSSL) {
RestTemplate restTemplate = null;
if (isSSL) {
try {
restTemplate = restTemplateSSL.restTemplateSSL();
} catch (Exception e) {
e.printStackTrace();
}
} else {
restTemplate = restTemplateBuilder.build();
}
return restTemplate;
}
Here is code related to SSL setting.
private static TrustManager[] createTrustManagers() {
TrustManager[] trustAllCerts;
trustAllCerts = new TrustManager[]{new X509ExtendedTrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] x509Certificates, String s){
}
@Override
public void checkServerTrusted(X509Certificate[] x509Certificates, String s) {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
@Override
public void checkClientTrusted(X509Certificate[] x509Certificates, String s, Socket socket) {
}
@Override
public void checkServerTrusted(X509Certificate[] x509Certificates, String s, Socket socket) {
}
@Override
public void checkClientTrusted(X509Certificate[] x509Certificates, String s, SSLEngine sslEngine) {
}
@Override
public void checkServerTrusted(X509Certificate[] x509Certificates, String s, SSLEngine sslEngine) {
}
}};
return trustAllCerts;
}
public RestTemplate restTemplateSSL() throws Exception {
SSLContext sslContext = SSLContext.getInstance(SSL_TLS);
sslContext.init(null, createTrustManagers(), new java.security.SecureRandom());
SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(sslContext,
NoopHostnameVerifier.INSTANCE);
final Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
.register(SSL_HTTPS, csf)
.build();
final PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(registry);
CloseableHttpClient httpClient = HttpClients.custom()
.setSSLSocketFactory(csf)
.setConnectionManager(cm)
.build();
HttpComponentsClientHttpRequestFactory requestFactory =
new HttpComponentsClientHttpRequestFactory();
requestFactory.setHttpClient(httpClient);
return new RestTemplate(requestFactory);
}
And this is the log I get.
PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target; nested exception is 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] with root cause
sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:141) ~[na:1.8.0_192]
at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126) ~[na:1.8.0_192]
at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280) ~[na:1.8.0_192]
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:392) ~[na:1.8.0_192]
at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:302) ~[na:1.8.0_192]
at sun.security.validator.Validator.validate(Validator.java:262) ~[na:1.8.0_192]
at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:324) ~[na:1.8.0_192]
at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:229) ~[na:1.8.0_192]
at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:124) ~[na:1.8.0_192]
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1621) ~[na:1.8.0_192]
at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:223) ~[na:1.8.0_192]
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:1037) ~[na:1.8.0_192]
at sun.security.ssl.Handshaker.process_record(Handshaker.java:965) ~[na:1.8.0_192]
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1064) ~[na:1.8.0_192]
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1367) ~[na:1.8.0_192]
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1395) ~[na:1.8.0_192]
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1379) ~[na:1.8.0_192]
at org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:436) ~[httpclient-4.5.9.jar:4.5.9]
at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:384) ~[httpclient-4.5.9.jar:4.5.9]
at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:142) ~[httpclient-4.5.9.jar:4.5.9]
at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:374) ~[httpclient-4.5.9.jar:4.5.9]
at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:393) ~[httpclient-4.5.9.jar:4.5.9]
at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:236) ~[httpclient-4.5.9.jar:4.5.9]
at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:186) ~[httpclient-4.5.9.jar:4.5.9]
at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89) ~[httpclient-4.5.9.jar:4.5.9]
at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110) ~[httpclient-4.5.9.jar:4.5.9]
at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185) ~[httpclient-4.5.9.jar:4.5.9]
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83) ~[httpclient-4.5.9.jar:4.5.9]
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:56) ~[httpclient-4.5.9.jar:4.5.9]
at org.springframework.http.client.HttpComponentsClientHttpRequest.executeInternal(HttpComponentsClientHttpRequest.java:87) ~[spring-web-5.1.8.RELEASE.jar:5.1.8.RELEASE]
at org.springframework.http.client.AbstractBufferingClientHttpRequest.executeInternal(AbstractBufferingClientHttpRequest.java:48) ~[spring-web-5.1.8.RELEASE.jar:5.1.8.RELEASE]
at org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:53) ~[spring-web-5.1.8.RELEASE.jar:5.1.8.RELEASE]
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:735) ~[spring-web-5.1.8.RELEASE.jar:5.1.8.RELEASE]
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:670) ~[spring-web-5.1.8.RELEASE.jar:5.1.8.RELEASE]
at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:579) ~[spring-web-5.1.8.RELEASE.jar:5.1.8.RELEASE]
I've read many other postings and stackoverflow Q&As
Access Https Rest Service using Spring RestTemplate
How to disable SSL certificate checking with Spring RestTemplate?
Disabling SSL Certificate Validation in Spring RestTemplate
and many more about this problem. But none worked out. I'm not sure how else I can try.