I am trying to perform POST request in Java. I have succeded with HTTP, but HTTPS is tricky for me. I am using this code:
// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(
java.security.cert.X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(
java.security.cert.X509Certificate[] certs, String authType) {
}
}
};
// Install the all-trusting trust manager
try {
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
} catch (Exception e) {
}
String httpsURL = "https://requestb.in/191g0961";
String query = "email="+URLEncoder.encode("[email protected]","UTF-8");
query += "&";
query += "password="+URLEncoder.encode("abcd","UTF-8") ;
URL myurl = new URL(httpsURL);
HttpsURLConnection con = (HttpsURLConnection)myurl.openConnection();
con.setRequestMethod("POST");
con.setRequestProperty("Content-length", String.valueOf(query.length()));
con.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
con.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0;Windows98;DigExt)");
con.setDoOutput(true);
con.setDoInput(true);
DataOutputStream output = new DataOutputStream(con.getOutputStream());
output.writeBytes(query);
output.close();
DataInputStream input = new DataInputStream(con.getInputStream());
for( int c = input.read(); c != -1; c = input.read() )
System.out.print( (char)c );
input.close();
System.out.println("Resp Code:"+con .getResponseCode());
System.out.println("Resp Message:"+ con .getResponseMessage());
I have added TrustManager in hope it solves my problem, because when I load my testing webpage https://requestb.in/191g0961 in Firefox, it says that site uses untrusted certificate, etc..
My code works with pages that are loaded in Firefox without any warnings, like this page: https://extranet.nix.cz/login (you can try it)
But with https://requestb.in/191g0961 it is giving me following exceptions:
Exception in thread "main" javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No subject alternative DNS name matching requestb.in found.
at sun.security.ssl.Alerts.getSSLException(Unknown Source)
at sun.security.ssl.SSLSocketImpl.fatal(Unknown Source)
at sun.security.ssl.Handshaker.fatalSE(Unknown Source)
at sun.security.ssl.Handshaker.fatalSE(Unknown Source)
at sun.security.ssl.ClientHandshaker.serverCertificate(Unknown Source)
at sun.security.ssl.ClientHandshaker.processMessage(Unknown Source)
at sun.security.ssl.Handshaker.processLoop(Unknown Source)
at sun.security.ssl.Handshaker.process_record(Unknown Source)
at sun.security.ssl.SSLSocketImpl.readRecord(Unknown Source)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source)
at sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source)
at sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source)
at sun.net.www.protocol.https.HttpsClient.afterConnect(Unknown Source)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(Unknown Source)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(Unknown Source)
at https.Sender.main(Sender.java:80)
Caused by: java.security.cert.CertificateException: No subject alternative DNS name matching requestb.in found.
at sun.security.util.HostnameChecker.matchDNS(Unknown Source)
at sun.security.util.HostnameChecker.match(Unknown Source)
at sun.security.ssl.X509TrustManagerImpl.checkIdentity(Unknown Source)
at sun.security.ssl.AbstractTrustManagerWrapper.checkAdditionalTrust(Unknown Source)
at sun.security.ssl.AbstractTrustManagerWrapper.checkServerTrusted(Unknown Source)
... 13 more
Have you any ideas how to solve this? Thanks in advance!
Solution:
I have created this simple class:
public class Verifier implements HostnameVerifier {
public boolean verify(String arg0, SSLSession arg1) {
return true; // mark everything as verified
}
}
and then I added:
con.setHostnameVerifier(new Verifier());
You also have to set a HostnameVerifier
in the HttpsURLConnection
. This has to verify that the hostname is accepted by your implementation.
I also suggest to not use this code in production environment as this code is likely to disable all security.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With