我正在使用Apache HttpClient在一些url上发送https帖子。
HttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url);
HttpResponse response = httpClient.execute(httpPost);
我得到了:
javax.net.ssl.SSLException: hostname in certificate didn't match: <*.*.*.*> != <*.url
现在,在搜索之后,我在堆栈溢出上找到了解决方案:
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);
这篇文章做得很成功。
但是我不明白这里发生了什么!我的连接仍然安全吗?这是正确的解决办法吗?如果不是,最好的解决方案是什么?
发布于 2013-03-19 03:55:43
如果您没有验证主机名,那么您只是没有检查您正在与您要交谈的实体对话:它可能是一个MITM。例如,这是与用卷曲禁用VERIFYHOST相同的问题。您也可能对关于Security.SE的这个问题感兴趣。
关于初始问题,证书中的主机名(或IP地址)需要与您要联系的主机名相匹配,即URL中的主机名。如果您使用的是IP地址,则该IP地址需要位于证书的主题替代名称中。(见这个问题.)一般来说,使用名称比使用IP地址更容易,甚至在局域网上也是如此。
编辑:考虑到您正在使用Apache 4.0.2,4.0.3的发行说明说:
这是一个紧急版本,修复SSL连接管理代码中的关键回归。HttpClient 4.0.2版本包括了对多家庭主机的改进支持,不幸的是,它有一个错误,导致默认的SSL主机名验证逻辑失败。使用HttpClient 4.0.2建立SSL连接的尝试可能导致javax.net.ssl.SSLException:“证书中的主机名不匹配.”错误。
发布于 2013-03-19 02:54:02
重要的是-如果您允许所有主机(即禁用主机名验证),那么它肯定不安全。你不应该在生产中这么做。
我认为您可能正在使用自签名证书,这可能是此异常的根本原因。如果是,请创建一个以主机作为本地主机(或您的IP)的证书,然后尝试。在生产中,只需启用主机名验证,您的代码就会运行良好。
https://stackoverflow.com/questions/15497372
复制相似问题