简体   繁体   中英

apache httpclient 4.4: HostnameVerifier transition from 4.3.x

HttpClient 4.3 had three static variables in org.apache.http.conn.ssl.SSLConnectionSocketFactory :

  1. STRICT_HOSTNAME_VERIFIER
  2. BROWSER_COMPATIBLE_HOSTNAME_VERIFIER
  3. ALLOW_ALL__HOSTNAME_VERIFIER

When upgrading the dependency to version 4.4 of HttpClient, I see that all the above constants are deprecated. The deprecation note in JavaDoc mentioned to use org.apache.http.conn.ssl.DefaultHostnameVerifier . Reading the docs, I assume that DefaultHostnameVerifier is a direct replacement to STRICT_HOSTNAME_VERIFIER . Also the ALLOW_ALL__HOSTNAME_VERIFIER is easy to implement:

package org.wiztools.restclient.http;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLSession;

/**
 *
 * @author subwiz
 */
public class AllowAllHostnameVerifier implements HostnameVerifier {

    @Override
    public boolean verify(String string, SSLSession ssls) {
        return true;
    }

}

There is a subtle distinction between the STRICT_HOSTNAME_VERIFIER and BROWSER_COMPATIBLE_HOSTNAME_VERIFIER (from JavaDoc):

The only difference between BROWSER_COMPATIBLE and STRICT is that a wildcard (such as "*.foo.com") with BROWSER_COMPATIBLE matches all subdomains, including "abfoo.com".

Do we have a readily available BROWSER_COMPATIBLE hostname verifier for httpclient 4.4?

实际上, AllowAllHostnameVerifier的javadoc直接替换了ALLOW_ALL__HOSTNAME_VERIFIER ,即NoopH​​ostnameVerifier

You don't need a new implementation class for AllowAllHostnameVerifier and don't need another implementation for BrowserCompatHostnameVerifier , simply pass an instance to the new DefaultHostnameVerifier ,

SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new DefaultHostnameVerifier());

this class the neccesary verification methods for both with the following method signatures

public final boolean verify(String host, SSLSession session) (Override)

and

public final void verify(String host, X509Certificate cert) throws SSLException

in the second method the httpcomponents does a checking for matching subdomains

public final void verify(String host, X509Certificate cert) throws SSLException {
    boolean ipv4 = InetAddressUtils.isIPv4Address(host);
    boolean ipv6 = InetAddressUtils.isIPv6Address(host);
    int subjectType = ((ipv4) || (ipv6)) ? 7 : 2;
    List subjectAlts = extractSubjectAlts(cert, subjectType);
    if ((subjectAlts != null) && (!(subjectAlts.isEmpty()))) {
        if (ipv4)
            matchIPAddress(host, subjectAlts);
        else if (ipv6)
            matchIPv6Address(host, subjectAlts);
        else {
            matchDNSName(host, subjectAlts, this.publicSuffixMatcher);
        }
    } else {
        X500Principal subjectPrincipal = cert.getSubjectX500Principal();
        String cn = extractCN(subjectPrincipal.getName("RFC2253"));
        if (cn == null) {
            throw new SSLException("Certificate subject for <" + host + "> doesn't contain " + "a common name and does not have alternative names");
        }

        matchCN(host, cn, this.publicSuffixMatcher);
    }
}

take a look at the source code for more clarification

org.apache.http.conn.ssl.DefaultHostnameVerifier

Hope this helps.

BrowserCompatHostnameVerifier was essentially IE 5/6 compatible implementation. I am no sure if it is actually compatible with more modern browser applications. BrowserCompatHostnameVerifier should have never existed in the first place and should not be used anymore.

I read all this and nothing worked for me, here's what saved my day: https://stackoverflow.com/a/36507502/3090309

I was using:

compile group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.5.2'

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM