Search code examples
javassljax-wshttpsurlconnection

Difference between HostnameVerifier and DefaultHostnameVerifier


I am implementing a hostname verifier for my SSL client. I know that the Default Hostname Verifier of the HTTPS URL connection is static. My problem is that I do not want the hostname verification to be static because I have multiple threads in my client accessing this hostname verifier at the same time.

At the moment my code looks like this,:

I have an inner class for the hostname verification,

public class CreateHostnameVerifier implements HostnameVerifier {
    @Override
    public boolean verify(String hostname, SSLSession session) {

            try {
                if (mInstance.getHost().equals(InetAddress.getByName(hostname)))
                    return true;
                else if (hostname.equals(mInstance.getHost().getHostAddress()))
                    return true;
                else if (hostname.equals(mInstance.getHost().getCanonicalHostName()))
                    return true;
                else
                    return false;

            } catch (UnknownHostException e) {
                System.out.println("Unknown Host");
            }
            return false;
        } 
    }
}

I call this class when I am building my endpoint,

address = mInstance.getSecureConnectionEndpoint();
try {
        HttpsURLConnection Connection = (HttpsURLConnection) address.openConnection();
        CreateHostnameVerifier hv = new CreateHostnameVerifier();
        Connection.setDefaultHostnameVerifier(hv);
        } catch (IOException e1) {
        e1.printStackTrace();
        }

Because I use setDefaultHostnameVerifer and try to access it in a non static way by doing Connection.setDefaultHostnameVerifier I get warnings like:

The static method setDefaultHostnameVerifier(HostnameVerifier) from the type HttpsURLConnection should be accessed in a static way

But this works absolutely fine, but in case I try to access it in a non-static way:

Connection.setHostnameVerifier(hv);

It does not work. Can someone explain me the difference between the two, i.e., setHostnameVerifer and setDefaultHostnameVerifier.


Solution

  • My problem is that I do not want the hostname verification to be static because I have multiple threads in my client accessing this hostname verifier at the same time.

    This "requirement" is based on a misapprehension.

    There is nothing per se wrong with multiple threads using the same HostnameVerifier. Unless you do something very strange, one of these objects should have no mutable state. Provided that your shared object HostnameVerifier instance is safely published (and immutable), it can be safely used by multiple threads without any need for synchronization.


    Can someone explain me the difference between the two, i.e., setHostnameVerifier and setDefaultHostnameVerifier.

    The javadoc for HttpsURLConnection.setHostnameVerifier explains it:

    public void setHostnameVerifier(HostnameVerifier v)

    Sets the HostnameVerifier for this instance. New instances of this class inherit the default static hostname verifier set by setDefaultHostnameVerifier. Calls to this method replace this object's HostnameVerifier.

    One possible reason that setHostnameVerifier is not working for you may be that you are calling it too late; i.e. after the connection has been established, and the verification has been performed.


    The way to avoid the warning is to set the default verifier like this:

        HttpsURLConnection.setDefaultHostnameVerifier(hv);
    

    It is a static method, so it should be called via the class name not via an instance reference. (That's what the warning is telling you ...)