我们如何在Android上的HttpClient 4.4+中启用SNI?

时间:2016-03-03 20:57:15

标签: android apache-httpclient-4.x

我正在尝试制定在现代版Android上使用SNI和主要HTTP堆栈的方法。这包括Apache独立的HttpClient库(不是这个版本加入到Android本身,已经死了,已经消失了。)

似乎最新版本的HttpClient不支持开箱即用的SNI。当我使用'cz.msebera.android:httpclient:4.4.1.1'工件时,我得到:

javax.net.ssl.SSLPeerUnverifiedException: Host name '...' does not match the certificate subject provided by the peer (CN=...)
at cz.msebera.android.httpclient.conn.ssl.SSLConnectionSocketFactory.verifyHostname(SSLConnectionSocketFactory.java:466)
at cz.msebera.android.httpclient.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:395)

(使用...编辑的主机名)

This HttpClient issue有一些代码可以解决这个问题。但是,目前尚不清楚如何使用它。 This Stack Overflow answer对实现有所帮助。然而,这反过来又崩溃了同样的例外:

javax.net.ssl.SSLPeerUnverifiedException: Host name '' does not match the certificate subject provided by the peer (CN=...)
at cz.msebera.android.httpclient.conn.ssl.SSLConnectionSocketFactory.verifyHostname(SSLConnectionSocketFactory.java:466)
at cz.msebera.android.httpclient.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:395)

这并不让我感到惊讶。建议的解决方法(用空字符串替换真正的主机名)让我觉得很奇怪。

This Stack Overflow question-and-answer基本上说“使用Java 1.7”,这对Android来说不是一个可行的选择。

那么,是否有人制定了使用Android兼容的HttpClient 4.4+环境启用SNI的方法?

1 个答案:

答案 0 :(得分:3)

尝试使用此版本的SSLConnectionSocketFactory,而不是使用Marek Sebera的HttpClient分支附带的版本。它包含了Andriod特定的代码。上次我用HttpClient 4.3的官方Apache端口测试了SNI,它运行得很好。

// Android specific code to enable SNI
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
    if (Log.isLoggable(TAG, Log.DEBUG)) {
        Log.d(TAG, "Enabling SNI for " + target);
    }
    try {
        Method method = sslsock.getClass().getMethod("setHostname", String.class);
        method.invoke(sslsock, target);
    } catch (Exception ex) {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "SNI configuration failed", ex);
        }
    }
}
// End of Android specific code