我正在尝试制定在现代版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的方法?
答案 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