我正在尝试使用https安全连接调用本地网络上托管的Web服务,起初出现了HostNameUnresolved
异常,因此我使用IP地址代替名称,现在我遇到了以下错误:
Error in geting tags.=javax.net.ssl.SSLException: 主机名在证书中不匹配: <10.100.248.99> !=
我已经将中间和根证书添加到了Android受信任列表中。
有没有人能给我一个解决方案,使我可以使用主机名而不是IP地址访问本地网络上托管的安全Web服务?
我正在尝试使用https安全连接调用本地网络上托管的Web服务,起初出现了HostNameUnresolved
异常,因此我使用IP地址代替名称,现在我遇到了以下错误:
Error in geting tags.=javax.net.ssl.SSLException: 主机名在证书中不匹配: <10.100.248.99> !=
我已经将中间和根证书添加到了Android受信任列表中。
有没有人能给我一个解决方案,使我可以使用主机名而不是IP地址访问本地网络上托管的安全Web服务?
要做到这一点,你需要做以下操作:
可写
从你的桌面Shell(以Linux为例,但在Windows上类似,并假设Android SDK已安装在/android-sdk
)执行以下命令:
cd /android-sdk/tools/
./emulator -avd NexusS -partition-size 128
其中NexusS是您设备的AVD名称。您必须
从命令行启动模拟器,否则在后续步骤中会出现错误。
现在打开另一个shell终端并获取您的模拟器/system/etc/hosts文件:
cd /android-sdk/platform-tools
./adb remount
./adb pull /system/etc/hosts /tmp/
remount
是为了将分区设置为可写。上面的pull
命令将主机文件复制到您桌面上的/tmp/hosts
。
从桌面编辑/tmp/hosts文件以符合您的需求,即如果Web服务是https://www.example.com/foo,IP地址是192.168.1.10:
127.0.0.1 locahost
192.168.1.10 www.example.com
cd /android-sdk/platform-tools
./adb push /tmp/hosts /system/etc/
现在您应该能够连接到Web服务。
请注意,如果使用自签名证书仍可能出现错误。
下面的图片是在编辑hosts
文件之前:
编辑后:
你应该使用 HostnameVerifier 来信任 Android 给定的主机。
HttpParams params = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(params, 5000);
HttpConnectionParams.setSoTimeout(params, 30000);
HostnameVerifier hostnameVerifier = org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER;
DefaultHttpClient httpClient = new DefaultHttpClient();
SchemeRegistry registry = new SchemeRegistry();
SSLSocketFactory socketFactory = SSLSocketFactory.getSocketFactory();
socketFactory.setHostnameVerifier((X509HostnameVerifier) hostnameVerifier);
registry.register(new Scheme("https", socketFactory, 443));
SingleClientConnManager mgr = new SingleClientConnManager(httpClient.getParams(), registry);
DefaultHttpClient client = new DefaultHttpClient(mgr, httpClient.getParams());
// Set verifier
HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);
我曾经在我的同事做的项目中看到过类似的错误,我们发现原因是如果你试图从主UI线程进行网络调用,Android系统会阻止它,尽管这个功能后来被引入API中,但之前它可以正常工作。这样做是为了减轻主UI线程的压力,所以我们创建了一个单独的服务,然后在其中提供了一个异步任务来进行网络调用。我不记得确切的API级别是什么时候引入的,但你可以在谷歌上查找,另外,你使用的API级别是多少?