且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

Android的:无法通过HTTPS访问本地网站

更新时间:2023-09-13 23:17:46

使用问题 https://开头的本地IP地址来访问SSL保护的网页是,这将很可能导致与浏览器信任网站的SSL证书的问题。

这是因为浏览器将试图通过检查主机名的HTTPS URL被用来验证SSL证书相匹配包含在SSL中的 CN = 主机名证书。

更新,以删除引用到本地主机(我原本以为本地托管的网站意味着相同的服务器浏览器,它与Android显然不是这样的):

您可以通过更改本地主机表,包括包含在SSL证书中的完全合格的主机名和名称与您要使用的特定IP地址关联避免此验证错误。

替代硬编码的IP地址在/ etc / hosts中

如果您对SSL证书是如何创建的,你可以添加额外的主机名,并使用使用者替代名称或SAN甚至IP地址到您的证书控制。如果您使用的是自签名证书,这可能是一个可行的选择。

不过,如果你的本地托管的网站,也可以从Internet访问你很可能使用的是购买SSL证书和硬编码的IP地址到这样的证书更将最有可能导致支持问题,随着时间的推移内部IP地址可以在需要回购的SSL证书时间而改变。

另一个选择可能是硬code您的内部IP地址,如果你有超过该服务器控制移动设备使用的DNS服务器。

I am trying to access a locally hosted website and get its HTML source to parse. I have few questions:

1) Can I use "https://An IP ADDRESS HERE" as a valid URL to try and access. I do not want to make changes in the /etc/hosts file so I want to do it this way.

2) I cannot get the html, since it is giving me Handshake exceptions and Certificate issues. I have tried a lot of help available over the web , but am not successful.

Here is the code I am using:

public class MainActivity extends Activity {
    private TextView textView;
    String response = "";
    String finalresponse="";


    /** Called when the activity is first created. */

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = (TextView) findViewById(R.id.TextView01);
        System.setProperty("javax.net.ssl.trustStore","C:\\User\\*" );
        System.setProperty("javax.net.ssl.trustStorePassword", "" );
    }

    private class DownloadWebPageTask extends AsyncTask<String, Void, String> {

        @Override
        protected String doInBackground(String... urls) {



            TrustManager[] trustAllCerts = new TrustManager[] {
                new X509TrustManager() {
                    public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                        return null;
                    }
                    public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) {
                    }
                    public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) {
                    }
                }
            };

            try {
                SSLContext sc = SSLContext.getInstance("SSL");
                sc.init(null, trustAllCerts, new java.security.SecureRandom());
                HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
            } catch (Exception e) {
            }


            try {
                URL url = new URL("https://172.27.224.133");

                HttpsURLConnection con =(HttpsURLConnection)url.openConnection();

                con.setHostnameVerifier(new AllowAllHostnameVerifier());
                finalresponse=readStream(con.getInputStream());
            } catch (Exception e) {
                e.printStackTrace();
            }
            return finalresponse;
        }

        private String readStream(InputStream in) {
            BufferedReader reader = null;
            try {
                reader = new BufferedReader(new InputStreamReader(in));
                String line = "";
                while ((line = reader.readLine()) != null) {
                    response+=line;
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (reader != null) {
                    try {
                        reader.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
            return response;
        } 


        @Override
        protected void onPostExecute(String result) {
            textView.setText(finalresponse);
        }
    }

    public void readWebpage(View view) {
        DownloadWebPageTask task = new DownloadWebPageTask();
        task.execute(new String[] { "https://172.27.224.133" });
    }
}

The problem with using https://local-ip-address to access an SSL protected web page is that this will most likely lead to an issue with the browser trusting the web site's SSL certificate.

This is because the browser will attempt to validate the SSL certificate by checking that the host name being used in the HTTPS URL matches the CN= host name contained inside the SSL certificate.

Updated to remove reference to localhost (I originally thought that locally hosted web site meant on the same server as the browser, which with Android is obviously not the case) :

You can avoid this validate error by changing your local host table to include the fully qualified host name contained in the SSL certificate and associating that name with the specific IP address you want to use.

Alternatives to hard-coding IP address in /etc/hosts

If you have control over how the SSL certificate is created you can add additional host names and even IP addresses to your certificate using Subject Alternate Names or SAN. This may be a viable option if you are using a self-signed certificate.

However, if your locally hosted web site is also accessed from the Internet you are more than likely using a purchased SSL certificate and hard-coding IP addresses into such a certificate will most likely lead to a support issue over time as internal IP address can change over time requiring repurchasing an SSL certificate.

Another option might be to hard-code your internal IP address into the DNS server that the mobile device is using if you have control over that server.