Android HttpClient - 证书中的主机名不匹配 <example.com> != <*.example.com>
Posted
技术标签:
【中文标题】Android HttpClient - 证书中的主机名不匹配 <example.com> != <*.example.com>【英文标题】:Android HttpClient - hostname in certificate didn't match <example.com> != <*.example.com> 【发布时间】:2010-06-28 19:52:53 【问题描述】:我在 android 上使用 HttpClient 连接到https://someUrl.com/somePath。问题是该站点的证书适用于 *.someUrl.com,而不是 someUrl.com,所以我收到 SSLException。是的,网站方面很蹩脚,但除非我能修复它,否则我会被卡住。有没有办法让 HttpClient 放松并接受证书?
【问题讨论】:
【参考方案1】:这是我的(编辑过的)解决方案:
class MyVerifier extends AbstractVerifier
private final X509HostnameVerifier delegate;
public MyVerifier(final X509HostnameVerifier delegate)
this.delegate = delegate;
@Override
public void verify(String host, String[] cns, String[] subjectAlts)
throws SSLException
boolean ok = false;
try
delegate.verify(host, cns, subjectAlts);
catch (SSLException e)
for (String cn : cns)
if (cn.startsWith("*."))
try
delegate.verify(host, new String[]
cn.substring(2) , subjectAlts);
ok = true;
catch (Exception e1)
if(!ok) throw e;
public DefaultHttpClient getTolerantClient()
DefaultHttpClient client = new DefaultHttpClient();
SSLSocketFactory sslSocketFactory = (SSLSocketFactory) client
.getConnectionManager().getSchemeRegistry().getScheme("https")
.getSocketFactory();
final X509HostnameVerifier delegate = sslSocketFactory.getHostnameVerifier();
if(!(delegate instanceof MyVerifier))
sslSocketFactory.setHostnameVerifier(new MyVerifier(delegate));
return client;
除非存在通配符域,否则它的优点是不会更改默认行为,在这种情况下,它会重新验证,就好像 2 部分域(例如,someUrl.com)是证书的一部分,否则原始异常是重新抛出。这意味着真正无效的证书仍然会失败。
【讨论】:
我尝试使用上述方法,但有时会出现堆栈溢出异常 - verify() 方法永远不会停止递归。在几十万次安装中,它每周发生大约 80 次。你有没有发现这方面的问题? @user291701 我已编辑代码以尝试解决您的问题。我猜问题是你最终再次在同一个工厂设置验证器,所以它最终以某种方式委托给自己......如果你找到更好的方法,请随时编辑我的答案。 无论如何,我都面临the server cannot service the request because the media type is unsupported
' 错误。对此原因没有任何线索。【参考方案2】:
Android 上的 BouncyCastle 太旧,无法识别通配符证书。
您可以编写自己的 X509TrustManager 来检查通配符。
如果您可以接受风险,您也可以完全禁用证书检查。看到这个问题,
Self-signed SSL acceptance on Android
【讨论】:
其实ZZ,如果OP关于站点名称和证书结构是正确的,那么错误信息是正确的: *.someUrl.com 应该是匹配 www.someUrl.com 和anything.someUrl.com,但不 someUrl.com 或this.that.someUrl.com。【参考方案3】:如果它想要*.someUrl.com
,那么看起来你可以给它www.someUrl.com/somePath
而不是someUrl.com/somePath
。
【讨论】:
不。 www.someUrl.com 重定向到 someUrl.com 我想那没用。你真的需要https吗?我猜是这样,但这会让生活更轻松。 当网站不进行重定向时,这是一个很好的临时解决方案!【参考方案4】:如果您使用 WebView,只需调用
webview.clearSslPreferences();
忽略 SSL 错误
【讨论】:
以上是关于Android HttpClient - 证书中的主机名不匹配 <example.com> != <*.example.com>的主要内容,如果未能解决你的问题,请参考以下文章
如何忽略 Apache HttpComponents HttpClient 5.1 中的 SSL 证书错误