【问题标题】:Android : java.io.IOException: Hostname was not verifiedAndroid:java.io.IOException:未验证主机名
【发布时间】:2014-01-07 11:27:29
【问题描述】:

在运行我的应用程序时出现 java.io.IOException:主机名未验证,我该如何解决?

java.io.IOException: Hostname '178.61.62.140' was not verified
01-03 16:34:37.613: W/System.err(17118):    at libcore.net.http.HttpConnection.verifySecureSocketHostname(HttpConnection.java:224)
01-03 16:34:37.615: W/System.err(17118):    at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.connect(HttpsURLConnectionImpl.java:454)
01-03 16:34:37.615: W/System.err(17118):    at libcore.net.http.HttpEngine.sendSocketRequest(HttpEngine.java:282)
01-03 16:34:37.616: W/System.err(17118):    at libcore.net.http.HttpEngine.sendRequest(HttpEngine.java:232)
01-03 16:34:37.617: W/System.err(17118):    at libcore.net.http.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:80)
01-03 16:34:37.617: W/System.err(17118):    at libcore.net.http.HttpURLConnectionImpl.getOutputStream(HttpURLConnectionImpl.java:194)
01-03 16:34:37.618: W/System.err(17118):    at libcore.net.http.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java:280)
01-03 16:34:37.618: W/System.err(17118):    at com.axis.cbk.httpmodel.CustHttpClient.executeHttpPost(CustHttpClient.java:120)
01-03 16:34:37.619: W/System.err(17118):    at com.axis.cbk.MainActivity$ProcessIt.doInBackground(MainActivity.java:237)
01-03 16:34:37.619: W/System.err(17118):    at com.axis.cbk.MainActivity$ProcessIt.doInBackground(MainActivity.java:1)
01-03 16:34:37.621: W/System.err(17118):    at android.os.AsyncTask$2.call(AsyncTask.java:264)
01-03 16:34:37.626: W/System.err(17118):    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
01-03 16:34:37.626: W/System.err(17118):    at java.util.concurrent.FutureTask.run(FutureTask.java:137)
01-03 16:34:37.627: W/System.err(17118):    at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:208)
01-03 16:34:37.628: W/System.err(17118):    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
01-03 16:34:37.630: W/System.err(17118):    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
01-03 16:34:37.631: W/System.err(17118):    at java.lang.Thread.run(Thread.java:856)
01-03 16:34:37.632: I/System.out(17118): [CDS]close[48194]
01-03 16:34:37.633: I/System.out(17118): close [socket][/0.0.0.0:48194]

【问题讨论】:

标签: android


【解决方案1】:

请注意 SSL 证书仅适用于域,而不适用于 IP 地址。

如果你使用IP,请在下面插入代码

HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier()
        {
            @Override
            public boolean verify(String hostname, SSLSession session)
            {
                if(hostname.equals("127.0.0.1 << your IP"))
                     return true;
            }
        });

【讨论】:

    【解决方案2】:

    您正在使用 IP 地址建立 HTTPS 连接。现在,SSL 证书绑定到 DNS 主机名,由于您没有使用 DNS 主机名进行连接,因此无法验证证书。

    使用实际的 DNS 名称进行连接,或者在极少数情况下,使用接受您的主机的 write your own hostname verifier(小心:很容易在此处引入漏洞)。

    【讨论】:

    • 使用 DNS 后出现 java.net.UnknownHostException: Unable to resolve host "******.com": No address associated with hostname
    • 哇,上周我一直在努力解决这个问题,非常感谢。请注意,如果您在代码中使用 IP 地址,最简单的解决方案是在 IP 末尾添加“nip.io”(或类似站点) - 它看起来像:“your_IP.nip。 io" 并像魅力一样工作
    【解决方案3】:

    @laalto 在他的回答中提出了一些很好的观点。还有一种替代解决方法,不需要对我在下面概述的 Android 代码进行任何更改。

    tl;dr - 修改 Android 设备上的 /etc/hosts 文件并添加一个新条目,将您的自签名证书公用名映射到您的开发服务器的 IP 地址。

    我在下面概述了完整的过程......

    像往常一样使用以下内容创建您的证书:

        sudo openssl genrsa -out key.pem 2048
        sudo openssl req -new -x509 -key key.pem -out cert.pem -days 1095
        sudo cat key.pem cert.pem >> stunnel.pem
    

    在第二个命令中,将公用名设置为您想要的任何域名,在此示例中,我将使用 testssl.com

    我正在使用 stunnel 代理我的 ssl 连接,因此第三个命令可能不适用。无论如何,一旦您的测试网站使用了您刚刚创建的证书,请在您的桌面上打开浏览器并导航到您的网站。如您所料,如果一切按预期进行,您应该会收到安全警告。查看证书并将其导出为带有链 (PEM) 的 X.509 证书。假设我们将其保存为 testssl.com

    现在运行以下命令,将其从 PEM 格式转换为可以下载到 Android 设备上的证书格式。

        openssl x509 -inform PEM -outform DM -in testssl.com -out testssl.com.crt
    

    现在您可以使用 adb 将您的证书推送到您的设备上。

        adb push testssl.com.crt /sdcard/testssl.com.crt
    

    在您的 Android 设备上,转到“设置”->“安全”->“从设备存储安装”。你应该看到你给证书的名字,对我来说是 testssl.com.crt

    要修改您的 /etc/hosts 文件,您需要将 /system 分区重新挂载为读写,不幸的是,您需要为此使用 su。

        adb shell
        su    
        mount -o rw,remount /system
    

    稍后我们会将 /system 分区恢复为只读。

    现在让我们抓取 hosts 文件,对其进行修改,然后使用以下命令将其放回设备上。

        adb shell
        su
        dd if=/etc/hosts of=/sdcard/hosts
        exit
        exit
        adb pull /sdcard/hosts
    

    您现在可以在主机文件中添加额外的一行,使其看起来类似于 [development_server_ip_address] [domain_name]。因此,假设我使用了上面详述的设置并且我的开发服务器的 IP 为 192.168.1.10,那么我将以下行添加到我的主机文件中:

        192.168.1.10     testssl.com
    

    您现在可以在运行以下命令后使用修改后的主机文件。

        adb push hosts /sdcard/hosts
        adb shell
        su
        dd if=/sdcard/hosts of=/etc/hosts
    

    要使 /system 分区只读,请从 adb shell 运行以下命令。

        mount -o ro,remount /system
    

    现在,您的 Android 应用以及任何其他使用 HTTPSUrlConnection 对象连接到您在 hosts 文件中添加的域名的应用都不会收到任何证书错误。最重要的是,您不必更改任何一行代码。

    【讨论】:

      猜你喜欢
      • 2015-08-25
      • 2020-11-15
      • 2013-01-15
      • 1970-01-01
      • 2015-11-30
      • 2019-01-20
      • 2021-09-19
      • 2018-05-24
      • 1970-01-01
      相关资源
      最近更新 更多