【问题标题】:Android Emulator not connecting to locally hosted webservice using httpsAndroid Emulator 未使用 https 连接到本地托管的 Web 服务
【发布时间】:2012-02-09 14:16:59
【问题描述】:

我正在尝试使用 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 服务?

【问题讨论】:

  • @Dark Rider 我正在尝试调用托管在本地网络而不是我的系统上的网络服务。我也无法从模拟器浏览器中查看它。
  • 查看此链接以了解 DNS 查找失败的原因:stackoverflow.com/questions/3184463/host-is-unresolved-in-lan
  • 使用将您的主机名与此内部 IP 匹配的本地 DNS。 (一个 hosts 文件可能就足够了)
  • SSL 握手将永远无法工作,除非证书的通用名称与您的服务的域名匹配......它在 Web 浏览器中工作的原因是您能够覆盖安全设置,但是,在代码中没有办法说,“请接受此名称不匹配” 您可以在本地计算机上创建一个与您的证书的通用名称匹配的 DNS(主机名)条目......或者创建一个具有通用名称的证书那是你的 IP 地址

标签: android web-services https ssl-certificate


【解决方案1】:

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

为此,您需要:

  • 挂载你的模拟器分区writeable

从您的桌面外壳(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文件前的图片:

编辑后:

【讨论】:

    【解决方案2】:

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

    【讨论】:

    • @Vikram 好的.. 当我们收到这个问题时,我的朋友正在使用 API 级别 2.3。我不确定它包含在哪个 API 级别,所以您可以尝试看看它是否适合您这样......如果它解决了你的问题,请告诉我......
    【解决方案3】:

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

    现在执行您想要在 client 对象上的请求。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-22
      • 2018-02-20
      • 2016-06-04
      • 2015-01-04
      • 2014-01-13
      • 2017-06-25
      相关资源
      最近更新 更多