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>的主要内容,如果未能解决你的问题,请参考以下文章

httpclient 和自签名证书的问题

HttpClient 证书错误

如何忽略 Apache HttpComponents HttpClient 5.1 中的 SSL 证书错误

忽略 Apache HttpClient 4.3 中的 SSL 证书

HttpClient证书错误

HttpClient 使用证书和跳过证书