Android模拟器未使用https连接到本地托管的Web服务

时间:2012-02-09 14:16:59

标签: android web-services https ssl-certificate

我正在尝试使用https安全连接调用本地网络上托管的Web服务,首先它提供了HostNameUnresolved的异常,所以我使用了ip地址而不是名称,现在我收到以下错误:

Error in geting tags.=javax.net.ssl.SSLException: hostname in certificate didn't match: <10.100.248.99> !=

我已经将中间证书和根证书添加到了android可信列表中。

有人能给我一个解决方案,使用主机名而不是ip地址访问本地网络上安全托管的Web服务吗?

3 个答案:

答案 0 :(得分:1)

我曾经在我的同事正在做的一个项目中看到类似的错误,我们发现的原因是,如果你试图从主ui线程进行网络调用,android系统会阻止它,尽管这个功能被引入到API之后就像以前一样工作正常。这样做是为了减少主ui线程的压力,所以我们创建了一个单独的服务,然后在其中我们提供了一个asynctask来进行网络调用。我不记得引入它的确切API级别,但你总是可以通过护目镜检查它,​​也可以通过你正在使用的API级别来检查它?

答案 1 :(得分:1)

正如其他人所说,您需要一些东西才能连接您的网络服务:
- 模拟器知道您需要连接的服务器的IP地址是什么 - 通过HTTPS连接的服务器名称URL必须解析为SSL证书的域

要做到这一点,你需要:

  • 安装您的模拟器分区writeable

从您的桌面shell(Linux的示例,但在Windows上类似,并假设在/android-sdk上安装了Android sdk):

cd /android-sdk/tools/
./emulator -avd NexusS -partition-size 128

其中NexusS是您设备的AVD名称。您MUST从命令行启动模拟器,否则您将在以后的步骤中收到错误。

现在打开另一个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/

您现在应该可以连接到网络服务了。

请注意,如果是自签名证书,您仍可能会遇到错误。

下面的图片是在编辑hosts文件之前:
IP doesn't match the certificate

编辑后:
Server name match

答案 2 :(得分:1)

您应该使用 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);

现在执行您想要客户端对象的请求。