SSL error from Java client, but POSTER form works in Firefox
I just install SSL certificates on my server. I'm sure they are configured correctly. When you navigate to https://mydomain.com/myapp
the browser, the page loads correctly, and a green block is displayed in the address bar.
Doing POST from Firefox> POSTER to this HTTPS
url I am getting a valid response.
If I do the same POST from my Java client, I get the following error:
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
On my server, I have put CA_ROOT certificates in JAVA ... / jre / lib / security / cacert keystore.
Here is my postcode from my Java client.
URL url = new URL(Global.SERVER_URL);
HttpsURLConnection connection = null;
connection = (HttpsURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setReadTimeout(45000);
connection.setRequestProperty("Content-Type", "text/json");
connection.connect();
PLease Note: THIS IS NOT THE MOST SIGNED CERT. It was released by CA
I have a feeling Glassfish is not shipping the complete Cert Chain. I looked at the certificate that the browser received and it was the complete certificate chain. I looked at the SSL error and it was only Intermediate Cert and for my domain.
How do I get Glassfish to send a complete Cert chain?
Check SSL chain
openssl.exe s_client -connect mydomain.com:443
Returns
WARNING: can't open config file: /usr/local/ssl/openssl.cnf
Loading 'screen' into random state - done
CONNECTED(00000190)
depth=0 C = US, ST = <edited>, L = <edited>, O = <edited>, OU = <edited>, CN = <edited>
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 C = US, ST = <edited>, L = <edited>, O = <edited>, OU = <edited>, CN = <edited>
verify error:num=27:certificate not trusted
verify return:1
depth=0 C = US, ST = <edited>, L = <edited>, O = <edited>, OU = <edited>, CN = <edited>
verify error:num=21:unable to verify the first certificate
verify return:1
---
Certificate chain
0 s:/C=US/ST=<edited>/L=<edited>/O=<edited>/OU=<edited>/CN=<edited>
i:/O=Cybertrust Inc/CN=Cybertrust Public SureServer SV CA
---
Server certificate
-----BEGIN CERTIFICATE-----
<edited>
-----END CERTIFICATE-----
subject=/C=US/ST=<edited>/L=<edited>/O=<edited>/OU=<edited>/CN=<edited>
issuer=/O=Cybertrust Inc/CN=Cybertrust Public SureServer SV CA
---
No client certificate CA names sent
---
SSL handshake has read 1676 bytes and written 513 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES128-GCM-SHA256
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
Protocol : TLSv1.2
Cipher : ECDHE-RSA-AES128-GCM-SHA256
Session-ID: <edited>
Session-ID-ctx:
Master-Key: <edited>
Key-Arg : None
PSK identity: None
PSK identity hint: None
SRP username: None
Start Time: 1410274974
Timeout : 300 (sec)
Verify return code: 21 (unable to verify the first certificate)
---
read:errno=0
Decision
The accepted answer from Bruno for the concept
Additional Information:
- Get Keystore Explorer. Its a fantastic GUI tool for browsing keystores.
- Open keystore.jks with Keystore explorer.
- Right click the Cert (mydomain) of interest and More> Certificate Chain Details .
- if it doesn't show the complete certification chain, add it by right clicking on the certificate Edit Certificate Chain> Add Certificate .
- Restart Glassfish.
source to share
---
Certificate chain
0 s:/C=US/ST=<edited>/L=<edited>/O=<edited>/OU=<edited>/CN=<edited>
i:/O=Cybertrust Inc/CN=Cybertrust Public SureServer SV CA
---
Contrary to what you said in the comment and according to this result, your server does not send an intermediate certificate. The certificate chain has only one certificate (at position 0): the server certificate.
On my server, I have put CA_ROOT certificates in JAVA ... / jre / lib / security / cacert keystore.
Adding intermediate certificates to the server-side trust server will not affect the chain presented by the server (it is only used to authenticate clients, if applicable).
You need to ensure that the keystore entry is configured with a full chain as described in this question , following the same procedure as this answer .
What you see in the browser may very well be the rebuilt chain and the browser may also know these intermediate CA certificates where the JRE cannot (different sets of trust bindings are used): you increase the likelihood that the JRE will default to your server certificate. correctly representing the whole chain. (Note that you don't need to present the CA root certificate in the chain, it doesn't hurt, but it's just network overhead.)
source to share
Browsers and Java use a different set of trusted root certificates, browsers get this information from the OS by default, Java maintains its own list, so it may be green in the browser and is not supported in Java
To check which certificates your Java version supports:
<jre_path>\bin\keytool -keystore "<jre_path>\lib\security\cacerts" -storepass changeit -list
And if you don't see your certificate, just add it to the file <jre_path>\lib\security\cacerts
.
source to share
SSLHandshakeException:
comes when the failed connection looks something like this. Usually indicating that there is some certificate validation issue, chances are your Truststore does not contain the trusted root certificates it needs. AND Indicates that the client and server cannot negotiate the desired security level. The connection is no longer in use.
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: A valid certification path could not be found for the requested target
An example to send an HTTP POST request using the below code.
private void sendPost() throws Exception {
String url = "https://selfsolve.apple.com/wcResults.do";
URL obj = new URL(url);
HttpsURLConnection con = (HttpsURLConnection) obj.openConnection();
//add reuqest header
con.setRequestMethod("POST");
con.setRequestProperty("User-Agent", "Mozilla/5.0");
con.setRequestProperty("Accept-Language", "en-US,en;q=0.5");
con.setRequestProperty("Content-Type", "text/json");
String urlParameters = "sn=C02G8416DRJM&cn=&locale=&caller=&num=12345";
// Send post request
con.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
wr.writeBytes(urlParameters);
wr.flush();
wr.close();
int responseCode = con.getResponseCode();
System.out.println("\nSending 'POST' request to URL : " + url);
System.out.println("Post parameters : " + urlParameters);
System.out.println("Response Code : " + responseCode);
BufferedReader in = new BufferedReader(
new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
//print result
System.out.println(response.toString());
}
if the response code is 200, then it looks good.
for more details to resolve the same exception see below links.
source to share