HttpClient:主机名不匹配 - 可从浏览器访问,但不能从代码访问

时间:2016-12-08 05:41:13

标签: java apache-httpclient-4.x

我正在尝试使用HttpClient从我的代码访问网站:

CloseableHttpClient httpclient = HttpClients.createDefault();

HttpGet httpget = new HttpGet("https://www.datamed.org/search.php?query=gene&searchtype=data");

ResponseHandler<String> responseHandler = new BasicResponseHandler();
String responseBody = httpclient.execute(httpget, responseHandler);

这是我得到的错误:

Exception in thread "main" javax.net.ssl.SSLException: hostname in certificate didn't match: <www.datamed.org> != <ucrexdc.ucsd.edu> OR <ucrexdc.ucsd.edu>

我从浏览器检查了证书,看起来是正确的,名字正确。 不确定它从哪里拿起ucrexdc.ucsd.edu

如果我使用代理,代码确实有效。 在StackOverflow上遇到了很多类似的问题,但在大多数情况下服务器都在用户的控制之下。就我而言,这是一个已经存在的网站。我只对这个网站有这个问题。

这对我的环境有问题吗?

更新:

我发现这两个网站(datamed.orgucrexdc.ucsd.edu)都拥有相同的IP 169.228.51.21。它可能是一个问题,为什么浏览器没有这个问题?

更新2:

我正在使用apache http-client 4.3.1
当我更新到4.4.1时,它已得到解决。这个问题很可能与SNI有关。

1 个答案:

答案 0 :(得分:0)

HttpClient为主机名验证提供了两种实现。

  1. DefaultHostnameVerifier
  2. NoopH​​ostnameVerifier
  3. 默认情况下,HttpClient使用 DefaultHostnameVerifier 实现。您可以尝试不同的主机名验证程序实现。

    SSLContext sslContext = SSLContexts.createSystemDefault();
    SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext,  NoopHostnameVerifier.INSTANCE);
    HttpClient httpClient = HttpClientBuilder.create().setSSLSocketFactory(sslsf).build();