java.io.IOException: Hostname was not verified

后端 未结 10 557
逝去的感伤
逝去的感伤 2020-11-28 06:27

I am trying to connect to a URL from a my Android app in Andorid Version 4.1.1, and I get the error indicated in the Title of my question, but when I tried to connect the sa

相关标签:
10条回答
  • 2020-11-28 06:58

    In addition to @Noam's answer, this is a complete example:

    /**
     * Disables the SSL certificate checking for new instances of {@link HttpsURLConnection} This has been created to
     * aid testing on a local box, not for use on production.
     */
    private static void disableSSLCertificateChecking() {
        TrustManager[] trustAllCerts = new TrustManager[] {
            new X509TrustManager() {
    
                @Override
                public void checkClientTrusted(java.security.cert.X509Certificate[] x509Certificates, String s) throws java.security.cert.CertificateException {
                    // not implemented
                }
    
                @Override
                public void checkServerTrusted(java.security.cert.X509Certificate[] x509Certificates, String s) throws java.security.cert.CertificateException {
                    // not implemented
                }
    
                @Override
                public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                    return null;
                }
    
            }
        };
    
        try {
    
            HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
    
                @Override
                public boolean verify(String s, SSLSession sslSession) {
                    return true;
                }
    
            });
            SSLContext sc = SSLContext.getInstance("TLS");
            sc.init(null, trustAllCerts, new java.security.SecureRandom());
            HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
    
        } catch (KeyManagementException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
    }
    

    Hope it helps

    0 讨论(0)
  • 2020-11-28 06:59

    This works better for me --> CHANGING StrictHostnameVerifier()

    https://developer.android.com/reference/org/apache/http/conn/ssl/StrictHostnameVerifier

    Example

        HostnameVerifier hostnameVerifier = new HostnameVerifier() {
        @Override
        public boolean verify(String hostname, SSLSession session) {
            HostnameVerifier hv = new StrictHostnameVerifier();
    
            return hv.verify("example.com", session);
           }
        };
    

    Use Example https://developer.android.com/training/articles/security-ssl#java

        // Tell the URLConnection to use our HostnameVerifier
        URL url = new URL("https://example.org/");
        HttpsURLConnection urlConnection = 
       (HttpsURLConnection)url.openConnection();
       urlConnection.setHostnameVerifier(hostnameVerifier);
    
    0 讨论(0)
  • 2020-11-28 07:06

    I experienced this problem in 4.1.1 and 4.1.2, using HTTPSUrlConnection.

    After some poking around I discovered that it was because the Apache server I am dealing with has multiple virtual hosts serving https traffic, resulting in SNI issues in Android - at least prior to JellyBean (I have unconfirmed reports that it was working in JB).

    In my case there were 3 virtual hosts serving https traffic:

    • mydomain.com
    • api.mydomain.com (the one I was trying to deal with)
    • admin.mydomain.com

    Probing api.* with openssl_client like this:

    openssl s_client -debug -connect api.mydomain.com:443
    

    ... always returned the root domain's certificate - buried in the output was something like:

    Certificate chain
     0 s:/OU=Domain Control Validated/CN=mydomain.com
     ...
    

    ... specifying the server name in the openssl_client command-line:

    openssl s_client -debug -servername api.mydomain.com -connect api.mydomain.com:443
    

    ... returned the certificate I was expecting to see:

    Certificate chain
     0 s:/OU=Domain Control Validated/CN=api.mydomain.com
    

    I was able to resolve the problem by moving the root domain virtual-host to a different physical host.

    It seems that the Android HostnameVerifier can live with multiple sub-domain's side-by-side as virtual hosts, but having the root domain as a virtual-host in the same apache caused issues.

    I am not a sys-admin/dev-ops and so it is possible that there are Apache config options that could have resolved the problem that I am not aware of.

    0 讨论(0)
  • 2020-11-28 07:13

    Please note SSL Certificate work only by Domain not work by IP address.

    if you use IP ,insert below code

    HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier()
            {
                @Override
                public boolean verify(String hostname, SSLSession session)
                {
                    if(hostname.equals("127.0.0.1"))
                         return true;
                }
            });
    
    0 讨论(0)
  • 2020-11-28 07:15

    From Amazon documentation: Bucket Restrictions

    "When using virtual hosted–style buckets with SSL, the SSL wild card certificate only matches buckets that do not contain periods. To work around this, use HTTP or write your own certificate verification logic."

    The easiest way seems to create a unique bucket name without periods:

    Instead of "bucketname.mycompany.com", something like "bucketnamemycompany" or any other DNS-compliant bucket name.

    0 讨论(0)
  • 2020-11-28 07:17

    In case you are running with certificates that doesn't mean anything and you want to bypass them you also need to add a null host name verifier to make this code work

    HttpsURLConnection.setDefaultHostnameVerifier(new NullHostNameVerifier());
    SSLContext context = SSLContext.getInstance("TLS");
    context.init(null, new X509TrustManager[]{new NullX509TrustManager()}, new SecureRandom());
    HttpsURLConnection.setDefaultSSLSocketFactory(context.getSocketFactory());
    

    And the code for the host:

    import javax.net.ssl.HostnameVerifier ;
    import javax.net.ssl.SSLSession;
    
    public class NullHostNameVerifier implements HostnameVerifier {
    
        @Override   
        public boolean verify(String hostname, SSLSession session) {
            Log.i("RestUtilImpl", "Approving certificate for " + hostname);
            return true;
        }
    
    }
    

    This needs to run once, but if you are making changes to your connection object you might need to run it again.

    0 讨论(0)
提交回复
热议问题