我们如何在 Android 上的 HttpClient 4.4+ 中启用 SNI?
How Do We Enable SNI in HttpClient 4.4+ on Android?
我正在尝试制定在 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 has some code that purports to address this. However, it is not clear exactly how to use it. 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 基本上说 "use Java 1.7",这不是 Android 的可行选项。
那么,有没有人想出在 Android 兼容的 HttpClient 4.4+ 环境中启用 SNI 的方法?
尝试使用此版本的 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
我正在尝试制定在 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 has some code that purports to address this. However, it is not clear exactly how to use it. 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 基本上说 "use Java 1.7",这不是 Android 的可行选项。
那么,有没有人想出在 Android 兼容的 HttpClient 4.4+ 环境中启用 SNI 的方法?
尝试使用此版本的 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