HTTP-соединение Android - PullRequest
99 голосов
/ 15 июня 2009

Я делаю пост https и получаю исключение ssl исключения. Сертификат ненадежного сервера. Если я делаю нормальный http, он работает отлично. Нужно ли как-то принимать сертификат сервера?

Ответы [ 14 ]

84 голосов
/ 16 июня 2009

Это то, что я делаю. Он просто больше не проверяет сертификат.

// always verify the host - dont check for certificate
final static HostnameVerifier DO_NOT_VERIFY = new HostnameVerifier() {
    public boolean verify(String hostname, SSLSession session) {
        return true;
    }
};

/**
 * Trust every server - dont check for any certificate
 */
private static void trustAllHosts() {
    // Create a trust manager that does not validate certificate chains
    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 {
        }
    } };

    // Install the all-trusting trust manager
    try {
        SSLContext sc = SSLContext.getInstance("TLS");
        sc.init(null, trustAllCerts, new java.security.SecureRandom());
        HttpsURLConnection
                .setDefaultSSLSocketFactory(sc.getSocketFactory());
    } catch (Exception e) {
        e.printStackTrace();
    }
}

и

    HttpURLConnection http = null;

    if (url.getProtocol().toLowerCase().equals("https")) {
        trustAllHosts();
        HttpsURLConnection https = (HttpsURLConnection) url.openConnection();
        https.setHostnameVerifier(DO_NOT_VERIFY);
        http = https;
    } else {
        http = (HttpURLConnection) url.openConnection();
    }
45 голосов
/ 15 июня 2009

Я догадываюсь, но если вы хотите, чтобы произошло фактическое рукопожатие, вы должны сообщить Android о вашем сертификате. Если вы хотите просто принять что бы то ни было, используйте этот псевдокод, чтобы получить то, что вам нужно, с HTTP-клиентом Apache:

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, но ни один из методов фактически не выполняет никакой работы, получите образец здесь .

Удачи!

33 голосов
/ 19 сентября 2010

Пытаясь ответить на этот вопрос, я нашел лучший учебник. С ним вам не нужно ставить под угрозу проверку сертификата.

http://blog.crazybob.org/2010/02/android-trusting-ssl-certificates.html

* Я не писал это, но спасибо Бобу Ли за работу

6 голосов
/ 22 октября 2010

Вы также можете посмотреть мою статью в блоге, очень похожую на crazybobs.

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

http://blog.antoine.li/index.php/2010/10/android-trusting-ssl-certificates/

4 голосов
/ 03 июня 2014

http://madurangasblogs.blogspot.in/2013/08/avoiding-javaxnetsslsslpeerunverifiedex.html

Предоставлено Мадуранга

При разработке приложения, использующего https, ваш тестовый сервер не имеет действительного сертификата SSL. Или иногда веб-сайт использует самозаверяющий сертификат или веб-сайт использует бесплатный SSL-сертификат. Поэтому, если вы попытаетесь подключиться к серверу, используя Apache HttpClient, вы получите исключение, сообщающее, что «узел не аутентифицирован». Хотя не стоит доверять всем сертификатам в производственном программном обеспечении, вам, возможно, придется делать это в зависимости от ситуации. Это решение устраняет исключение, вызванное «одноранговый не аутентифицирован».

Но прежде чем мы перейдем к решению, я должен предупредить вас, что это не очень хорошая идея для производственного приложения. Это нарушит цель использования сертификата безопасности. Поэтому, если у вас нет веских причин или вы уверены, что это не вызовет никаких проблем, не используйте это решение.

Обычно вы создаете HttpClient вот так.

HttpClient httpclient = new DefaultHttpClient();

Но вы должны изменить способ создания HttpClient.

Сначала вы должны создать класс, расширяющий org.apache.http.conn.ssl.SSLSocketFactory.

import org.apache.http.conn.ssl.SSLSocketFactory;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

public class MySSLSocketFactory extends SSLSocketFactory {
         SSLContext sslContext = SSLContext.getInstance("TLS");

    public MySSLSocketFactory(KeyStore truststore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
        super(truststore);

        TrustManager tm = new X509TrustManager() {
            public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            }

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

            public X509Certificate[] getAcceptedIssuers() {
                return null;
            }
        };

        sslContext.init(null, new TrustManager[] { tm }, null);
    }

    @Override
    public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException {
        return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);
    }

    @Override
    public Socket createSocket() throws IOException {
        return sslContext.getSocketFactory().createSocket();
    }
}

Затем создайте метод, подобный этому.

public HttpClient getNewHttpClient() {
     try {
         KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
         trustStore.load(null, null);

         SSLSocketFactory sf = new MySSLSocketFactory(trustStore);
         sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

         HttpParams params = new BasicHttpParams();
         HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
         HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);

         SchemeRegistry registry = new SchemeRegistry();
         registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
         registry.register(new Scheme("https", sf, 443));

         ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry);

         return new DefaultHttpClient(ccm, params);
     } catch (Exception e) {
         return new DefaultHttpClient();
     }
}

Тогда вы можете создать HttpClient.

HttpClient httpclient = getNewHttpClient();

Если вы пытаетесь отправить почтовый запрос на страницу входа, остальная часть кода будет выглядеть следующим образом.

private URI url = new URI("url of the action of the form");
HttpPost httppost =  new HttpPost(url);
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();  
nameValuePairs.add(new BasicNameValuePair("username", "user"));  
nameValuePairs.add(new BasicNameValuePair("password", "password"));
try {
    httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
    HttpResponse response = httpclient.execute(httppost);
    HttpEntity entity = response.getEntity();
    InputStream is = entity.getContent();
} catch (UnsupportedEncodingException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
} catch (ClientProtocolException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
} catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}

Вы получаете html-страницу для InputStream. Затем вы можете делать все, что захотите, с возвращенной HTML-страницей.

Но здесь вы столкнетесь с проблемой. Если вы хотите управлять сеансом с помощью файлов cookie, вы не сможете сделать это с помощью этого метода. Если вы хотите получить куки, вы должны будете сделать это через браузер. Только тогда вы получите куки.

3 голосов
/ 19 сентября 2013

Если вы используете сертификат StartSSL или Thawte, он не будет работать для Froyo и более старых версий. Вы можете использовать репозиторий CAcert более новой версии вместо того, чтобы доверять каждому сертификату.

2 голосов
/ 05 октября 2012

Любой из этих ответов не работал для меня, поэтому вот код, который доверяет любым сертификатам.

import java.io.IOException;

    import java.net.Socket;
    import java.security.KeyManagementException;
    import java.security.KeyStoreException;
    import java.security.NoSuchAlgorithmException;
    import java.security.UnrecoverableKeyException;
    import java.security.cert.CertificateException;
    import java.security.cert.X509Certificate;

    import javax.net.ssl.SSLContext;
    import javax.net.ssl.TrustManager;
    import javax.net.ssl.X509TrustManager;

    import org.apache.http.client.ClientProtocolException;
    import org.apache.http.client.HttpClient;
    import org.apache.http.client.methods.HttpPost;
    import org.apache.http.conn.scheme.PlainSocketFactory;
    import org.apache.http.conn.scheme.Scheme;
    import org.apache.http.conn.scheme.SchemeRegistry;
    import org.apache.http.conn.ssl.SSLSocketFactory;
    import org.apache.http.conn.ssl.X509HostnameVerifier;
    import org.apache.http.impl.client.DefaultHttpClient;
    import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
    import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;

    public class HttpsClientBuilder {
        public static DefaultHttpClient getBelieverHttpsClient() {

            DefaultHttpClient client = null;

            SchemeRegistry Current_Scheme = new SchemeRegistry();
            Current_Scheme.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
            try {
                Current_Scheme.register(new Scheme("https", new Naive_SSLSocketFactory(), 8443));
            } catch (KeyManagementException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (UnrecoverableKeyException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (NoSuchAlgorithmException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (KeyStoreException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            HttpParams Current_Params = new BasicHttpParams();
            int timeoutConnection = 8000;
            HttpConnectionParams.setConnectionTimeout(Current_Params, timeoutConnection);
            int timeoutSocket = 10000;
            HttpConnectionParams.setSoTimeout(Current_Params, timeoutSocket);
            ThreadSafeClientConnManager Current_Manager = new ThreadSafeClientConnManager(Current_Params, Current_Scheme);
            client = new DefaultHttpClient(Current_Manager, Current_Params);
            //HttpPost httpPost = new HttpPost(url);
            //client.execute(httpPost);

         return client;
         }

    public static class Naive_SSLSocketFactory extends SSLSocketFactory
    {
        protected SSLContext Cur_SSL_Context = SSLContext.getInstance("TLS");

        public Naive_SSLSocketFactory ()
                throws NoSuchAlgorithmException, KeyManagementException,
                KeyStoreException, UnrecoverableKeyException
        {
            super(null, null, null, null, null, (X509HostnameVerifier)null);
            Cur_SSL_Context.init(null, new TrustManager[] { new X509_Trust_Manager() }, null);
        }

        @Override
        public Socket createSocket(Socket socket, String host, int port,
                boolean autoClose) throws IOException
        {
            return Cur_SSL_Context.getSocketFactory().createSocket(socket, host, port, autoClose);
        }

        @Override
        public Socket createSocket() throws IOException
        {
            return Cur_SSL_Context.getSocketFactory().createSocket();
        }
    }

    private static class X509_Trust_Manager implements X509TrustManager
    {

        public void checkClientTrusted(X509Certificate[] chain, String authType)
                throws CertificateException {
            // TODO Auto-generated method stub

        }

        public void checkServerTrusted(X509Certificate[] chain, String authType)
                throws CertificateException {
            // TODO Auto-generated method stub

        }

        public X509Certificate[] getAcceptedIssuers() {
            // TODO Auto-generated method stub
            return null;
        }

    };
}
2 голосов
/ 31 октября 2010

Ничего из этого не помогло мне (усугубляется также ошибкой Thawte ). В конце концов я исправил это с помощью Самозаверяющего принятия SSL на Android и Пользовательская обработка SSL перестала работать на Android 2.2 FroYo

1 голос
/ 01 апреля 2012

Это известная проблема с Android 2.x. Я боролся с этой проблемой в течение недели, пока не наткнулся на следующий вопрос, который не только дает хорошее представление о проблеме, но также обеспечивает рабочее и эффективное решение без каких-либо пробелов в безопасности.

Ошибка «Нет сертификата пира» в Android 2.3, но НЕ в 4

1 голос
/ 15 июня 2009

Я не знаю об особенностях Android для ssl-сертификатов, но было бы разумно, чтобы Android не принимал самоподписанный ssl-сертификат. Я нашел этот пост на форумах Android, который, кажется, решает ту же проблему: http://androidforums.com/android-applications/950-imap-self-signed-ssl-certificates.html

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...