When you create a self signed certificate to enable HTTPS on your local server for test, and then a java client (it can be the webapp itself) tries to access your localhost, it might face the following exception:
Caused by: javax.net.ssl.SSLHandshakeException:
java.security.cert.CertificateException: No name matching localhost found
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:174)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1611)
at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:187)
at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:181)
......
Caused by: java.security.cert.CertificateException: No name matching localhost found
at sun.security.util.HostnameChecker.matchDNS(HostnameChecker.java:210)
at sun.security.util.HostnameChecker.match(HostnameChecker.java:77)
......
This happens because, quoting from lots of places out there:
Java by default verifies that the certificate CN (Common Name) is the same as host name in the URL. If the CN in the certificate is not the same as the host name, your web service client fails.
So, a valid solution would be create an implementation of HostnameVerifier that returns ok for localhost, regardless of the certificate. Something like:
javax.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier(
new javax.net.ssl.HostnameVerifier(){
public boolean verify(String hostname,
javax.net.ssl.SSLSession sslSession) {
if (hostname.equals("localhost")) {
return true;
}
return false;
}
});
The problem of this approach is that you have to add new code to the client, be careful to remove it for production, and if your client is another webapp, it will probably mean another deploy (it gets worse when you don’t own the code of the app.
An easier solution to this problem would be simply create your self-signed certificate with the “localhost” CN.
So, lets say we are following this article for setting up SSL on Tomcat. Then, instead of:
keytool -genkey -alias tomcat -keyalg RSA Enter keystore password: password Re-enter new password: password What is your first and last name? [Unknown]: Your Own Name What is the name of your organizational unit? [Unknown]: home What is the name of your organization? [Unknown]: home What is the name of your City or Locality? [Unknown]: City What is the name of your State or Province? [Unknown]: State What is the two-letter country code for this unit? [Unknown]: US Is CN=Your Own Name, OU=home, O=home, L=City, ST=State, C=US correct?
Change the CN (your name) to localhost
keytool -genkey -alias tomcat -keyalg RSA Enter keystore password: password Re-enter new password: password What is your first and last name? [Unknown]: localhost What is the name of your organizational unit? [Unknown]: home What is the name of your organization? [Unknown]: home What is the name of your City or Locality? [Unknown]: City What is the name of your State or Province? [Unknown]: State What is the two-letter country code for this unit? [Unknown]: US Is CN=localhost, OU=home, O=home, L=City, ST=State, C=US correct?
Done. Set your webserver up to use the new certificate and the clients will accept it.



Pingback: Apache Tomcat and SSL | martin steffen