Подтвердить что ты не робот

Java.io.IOException: имя хоста не проверено

Я пытаюсь подключиться к URL-адресу из моего приложения Android в Andorid Version 4.1.1, и я получаю сообщение об ошибке, указанное в заголовке моего вопроса, но когда я попытался подключить тот же URL-адрес от Andorid версии 4.0. 4 или 3.1, все работает нормально.

Фрагмент кода:

    try {
        .
        .
        .
        URL url = new URL(urlStr);
        Log.i(TAG,"[ URL ] " + urlStr);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        int size = conn.getContentLength();
        int responsecode = conn.getResponseCode();
        Log.d(TAG, "Responsecode: " + responsecode);
        .
        .
        .
        } catch (Exception e) {
        e.printStackTrace();
        }


private static void trustAllHosts() {

        TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                    return new java.security.cert.X509Certificate[] {};
            }

            public void checkClientTrusted(X509Certificate[] chain,
                            String authType) throws CertificateException {
            }

            public void checkServerTrusted(X509Certificate[] chain,
                            String authType) throws CertificateException {
            }
        } };

        try {
                SSLContext sc = SSLContext.getInstance("TLS");
                sc.init(null, trustAllCerts, new java.security.SecureRandom());
                HttpsURLConnection
                                .setDefaultSSLSocketFactory(sc.getSocketFactory());
        } catch (Exception e) {
                System.out.println("IOException : HTTPSRequest::trustAllHosts");
                e.printStackTrace();
        }
    }

Но здесь я понимаю одно: "Возможно, сертификат - это самозаверяющие сертификаты и не включает их в KeyStore.

Я не понимаю, почему это исключение происходит только в ОС Android Verison 4.1.1 Спасибо.

FULL STACK TRACE

01-31 10:26:08.348: W/System.err(3158): java.io.IOException: Hostname <URL> was not verified
01-31 10:26:08.348: W/System.err(3158):     at libcore.net.http.HttpConnection.verifySecureSocketHostname(HttpConnection.java:223)
01-31 10:26:08.348: W/System.err(3158):     at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.connect(HttpsURLConnectionImpl.java:446)
01-31 10:26:08.348: W/System.err(3158):     at libcore.net.http.HttpEngine.sendSocketRequest(HttpEngine.java:289)
01-31 10:26:08.348: W/System.err(3158):     at libcore.net.http.HttpEngine.sendRequest(HttpEngine.java:239)
01-31 10:26:08.348: W/System.err(3158):     at libcore.net.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:273)
01-31 10:26:08.348: W/System.err(3158):     at libcore.net.http.HttpURLConnectionImpl.getHeaderField(HttpURLConnectionImpl.java:130)
01-31 10:26:08.348: W/System.err(3158):     at java.net.URLConnection.getHeaderFieldInt(URLConnection.java:544)
01-31 10:26:08.348: W/System.err(3158):     at java.net.URLConnection.getContentLength(URLConnection.java:316)
01-31 10:26:08.348: W/System.err(3158):     at libcore.net.http.HttpsURLConnectionImpl.getContentLength(HttpsURLConnectionImpl.java:191)
01-31 10:26:08.348: W/System.err(3158):     at com.ih.util.HelpVideoServices$downloadTask.run(HelpVideoServices.java:172)                                
4b9b3361

Ответ 1

Если вы работаете с сертификатами, которые ничего не значат, и вы хотите обойти их, вам также нужно добавить нулевой верификатор имени хоста, чтобы этот код работал

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

И код для хоста:

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;
    }

}

Это нужно запустить один раз, но если вы вносите изменения в объект подключения, вам может потребоваться запустить его снова.

Ответ 2

В дополнение к ответу @Noam это полный пример:

/**
 * 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();
    }
}

Надеюсь, что это поможет

Ответ 3

Это может произойти из-за того, что CN (общее имя), которое вы объявили на своем SSL, не обрабатывает фактический URL-адрес, по которому вы также отправляете свой HTTP-запрос.

Если это так, создайте новый SSL и введите currect CN. Это должно решить проблему.

Ответ 4

Я столкнулся с этой проблемой в 4.1.1 и 4.1.2, используя HTTPSUrlConnection.

После некоторого разговора я обнаружил, что это связано с тем, что сервер Apache, с которым я имею дело, имеет несколько виртуальных хостов, обслуживающих трафик https, в результате чего

Ответ 5

Android не может настроить SSL-соединение, я полагаю. Возможно, ваш сертификат для другого имени хоста, а не тот, с которым вы устанавливаете соединение. Прочитайте docs здесь и здесь.

Ответ 6

возможно, что ваша проблема заключается в том, что ваш URL был разрешен с помощью "https". вы должны преобразовать все строковые URL-адреса в "http", и он будет работать.

EDIT:

SchemeRegistry schemeRegistry = new SchemeRegistry ();

schemeRegistry.register (new Scheme ("http",
    PlainSocketFactory.getSocketFactory (), 80));
schemeRegistry.register (new Scheme ("https",
    new CustomSSLSocketFactory (), 443));

ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager (
    params, schemeRegistry);

return new DefaultHttpClient (cm, params);

CustomSSLSocketFactory:

public class CustomSSLSocketFactory extends org.apache.http.conn.ssl.SSLSocketFactory
{
    private SSLSocketFactory FACTORY = HttpsURLConnection.getDefaultSSLSocketFactory ();

    public CustomSSLSocketFactory ()
    {
        super(null);
        try
        {
            SSLContext context = SSLContext.getInstance ("TLS");
            TrustManager[] tm = new TrustManager[] { new FullX509TrustManager () };
            context.init (null, tm, new SecureRandom ());

            FACTORY = context.getSocketFactory ();
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }

    public Socket createSocket() throws IOException
    {
        return FACTORY.createSocket();
    }

    // TODO: add other methods like createSocket() and getDefaultCipherSuites().
    // Hint: they all just make a call to member FACTORY 
}

FullX509TrustManager - это класс, который реализует javax.net.ssl.X509TrustManager, но ни один из методов не выполняет какую-либо работу, получите образец [здесь] [1].

Удачи!

Ответ 7

Из документации Amazon: Ограничения в ковше

"При использовании виртуальных хостинговых ведер с SSL, сертификат Wild Card SSL соответствует только кодам, которые не содержат периодов. Чтобы обойти это, используйте HTTP или напишите собственную логику проверки сертификата.

Самый простой способ - создать уникальное имя ведра без периодов:

Вместо "bucketname.mycompany.com", что-то вроде "bucketnamemycompany" или любого другого DNS-совместимого имени ведра.