Reputation: 4306
I am trying to call HTTPS web service, this is the code i use, this function is deployed on AWS instance with OS amazon linux
public static <T> T postSecureJsonRequest(String url, Object request, Type responseType) throws Exception {
BufferedReader br;
HttpsURLConnection con = null;
try {
URL obj = new URL(null, url, new sun.net.www.protocol.https.Handler());
con = (HttpsURLConnection) obj.openConnection();
con.setReadTimeout(IntegrationConfiguration.getConnectionTimeOut());
con.setRequestMethod("POST");
con.setRequestProperty("Content-Type", "application/json");
con.setRequestProperty("Accept", "application/json");
con.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
if (request.getClass().equals(String.class)) {
wr.writeBytes(request + "");
} else {
wr.writeBytes(gson.toJson(request));
}
wr.flush();
wr.close();
if (con.getResponseCode() != 200) {
throw new Exception(IntegrationConstants.TECHNICAL_ERROR + " "
+ ("failed : HTTP error code : " + con.getResponseCode() + " from the main server : " + url));
}
br = new BufferedReader(new InputStreamReader((con.getInputStream())));
String inputLine;
StringBuffer outputResponse = new StringBuffer();
while ((inputLine = br.readLine()) != null) {
outputResponse.append(inputLine);
}
return (T) gson.fromJson(outputResponse.toString(), responseType);
} catch (Exception e) {
throw e;
} finally {
if (con != null) {
con.disconnect();
}
}
}
the problem is that function is always throw an Exception
javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.Alerts.getSSLException(Alerts.java:154)
at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:1989)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1096)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1342)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1369)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1353)
at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:559)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(HttpURLConnection.java:1157)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java:259)
at com.wsg.bit.casino.integration.util.IntegrationUtility.postSecureJsonRequest(IntegrationUtility.java:524)
what i am missing here ?
EDIT:I got these information from the server
* TCP_NODELAY set
* Connected to api..... (1xx.2xx.1xx.1xx) port 443 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
* CAfile: /etc/pki/tls/certs/ca-bundle.crt
CApath: none
* ALPN, server accepted to use http/1.1
* SSL connection using TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
* Server certificate:
* subject: CN=api.....
* start date: Apr 27 09:29:11 2018 GMT
* expire date: Jul 26 09:29:11 2018 GMT
* common name: api.server1.ih.testenv.io
* issuer: CN=Let's Encrypt Authority X3,O=Let's Encrypt,C=US
> GET / HTTP/1.1
> Host: api.server1.ih.testenv.io
> User-Agent: curl/7.53.1
> Accept: */*
>
< HTTP/1.1 404 Not Found
< Server: nginx/1.10.3 (Ubuntu)
< Date: Thu, 03 May 2018 08:43:05 GMT
< Content-Type: application/json; charset=utf-8
< Content-Length: 39
< Connection: keep-alive
< cache-control: max-age=0, private, must-revalidate
< x-request-id: 2klhbq0t5ahtlndlmc0003k2
Edit: when i call the HTTPS
service from another REST
client like postman
it works fine
Upvotes: 1
Views: 1623
Reputation: 2318
You need to import the chain of certificates in java keystore. If they are private certificates, you can ask for certificates from the web service owner. If they are public certificates you can open the web service link in any standard browser and download the chain of certificates.
Refer below links for importing them:
How do I find out what keystore my JVM is using?
How to import a .cer certificate into a java keystore?
You can also create a custom keystore and import certificates in it and configure the same in your code.
If you get past this issue, you are likely to get hostverification exception. For resolving that you can insert the below code.
javax.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier(new javax.net.ssl.HostnameVerifier() {
public boolean verify(String hostname, javax.net.ssl.SSLSession sslSession) {
return hostname.equals("www.domainname.com");
}
});
Upvotes: 1