Java HTTP post using HTTPS Confusion - javax.net.ssl.SSLException: hostname in certificate didn't match
java, security, ssl, ssl-certificate, web-services
Solution
If you're not verifying the host name, you're simply not checking that you're talking to the entity you intended to talk to: it could be a MITM instead. It's the same issue as disabling VERIFYHOST with Curl, for example. You may also be interested in this question on Security.SE.
Regarding your initial problem, the host name (or IP address) in the certificate needs to match the host name you intended to contact, that is, the one in the URL. If you're using an IP address, that IP address needs to be in the Subject Alternative Name of the certificate. (See this question.) In general, it's easier to use names rather than IP addresses, even on a LAN.
EDIT: Considering you're using Apache Http Client 4.0.2, the release notes for 4.0.3 say:
This is an emergency release fixing a critical regression in the SSL connection management code. HttpClient 4.0.2 release included an improved support for multihome hosts, which unfortunately had a bug causing the default SSL hostname verification logic to fail. An attempt to establish an SSL connection with HttpClient 4.0.2 can result in javax.net.ssl.SSLException: "hostname in certificate didn't match ..." error.
Problem
I'm sending an https POST on some url using Apache HttpClient. ``` HttpClient httpClient = new DefaultHttpClient(); HttpPost httpPost = new HttpPost(url); HttpResponse response = httpClient.execute(httpPost); ``` And I get: ``` javax.net.ssl.SSLException: hostname in certificate didn't match: <*.*.*.*> != <*.url ``` Now after searching, I found the solution on stackoverflow: ``` HostnameVerifier hostnameVerifier = org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER; SchemeRegistry registry = new SchemeRegistry(); SSLSocketFactory socketFactory = SSLSocketFactory.getSocketFactory(); socketFactory.setHostnameVerifier((X509HostnameVerifier) hostnameVerifier); registry.register(new Scheme("https", socketFactory, 443)); SingleClientConnManager mgr = new SingleClientConnManager(client.getParams(), registry); HttpClient httpClient = new DefaultHttpClient(mgr, client.getParams()); HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier); ``` And the POST is succesfully done. But I don't understand what's happening here! Is my connection still secure? Is this the right solution? If not, what's the best solution?