Android HttpClient - 证书中的主机名与<example.com>不匹配!=&lt; * .example.com&gt; </example.com>

时间:2010-06-28 19:52:54

标签: java android ssl httpclient wildcard-subdomain

我在Android上使用HttpClient连接到https://someUrl.com/somePath。问题是网站的证书是针对* .someUrl.com而不是someUrl.com的,所以我得到了一个SSLException。网站上有跛脚,是的,但除非我能解决这个问题,否则我会陷入困境。有没有办法让HttpClient放松并接受证书?

4 个答案:

答案 0 :(得分:33)

这是我的(已编辑)解决方案:

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)是证书的一部分,否则原始异常是重新抛出。这意味着真正无效的证书仍然会失败。

答案 1 :(得分:3)

Android上的BouncyCastle太旧了,它无法识别通配符证书。

您可以编写自己的X509TrustManager来检查通配符。

或者如果您可以接受风险,则可以完全禁用证书检查。看到这个问题,

Self-signed SSL acceptance on Android

答案 2 :(得分:1)

如果它需要*.someUrl.com,那么您似乎可以将其www.someUrl.com/somePath代替someUrl.com/somePath

答案 3 :(得分:1)

如果您使用WebView只需调用

webview.clearSslPreferences();

忽略SSL错误