Android - Как принимать любые сертификаты, используя HttpClient и передавая сертификат одновременно - PullRequest
3 голосов
/ 27 сентября 2011

У меня есть сценарий, в котором я должен передать сертификат на свой сервер, а затем сервер отправляет мне свой сертификат, который я должен принять для доступа к серверу.Я использовал для этого HttpURLConnection без проблем.

Однако недавно у меня возникла проблема с HttpURLConnection.Код, который я использовал, получил изображение с сервера HTTPS.Если изображение было маленьким (<500 КБ), никаких проблем не возникало.Однако с большими изображениями я получил это: </p>

javax.net.ssl.SSLProtocolException: Ошибка чтения: ssl = 0x3c97e8: сбой в библиотеке SSL, обычно ошибка протокола

Я читал об этомв Интернете, и многие люди говорили, что использование HttpClient вместо HttpURLConnection было подходящим способом (например, этот сайт http://soan.tistory.com/62, думаю, что он написан на корейском, я не могу его прочитать, но это то, что я думаюэто говорит).

Это мой старый код, использующий URLConnection:

    public static URLConnection CreateFromP12(String uri, String keyFilePath,
        String keyPass, TrustManager[] trustPolicy, HostnameVerifier hv) {
    try {

        SSLContext sslContext = SSLContext.getInstance("TLS");
        KeyStore keyStore = KeyStore.getInstance("PKCS12");
        KeyManagerFactory kmf = KeyManagerFactory.getInstance("X509");

        keyStore.load(new FileInputStream(keyFilePath),
                keyPass.toCharArray());

        kmf.init(keyStore, keyPass.toCharArray());
        sslContext.init(kmf.getKeyManagers(), trustPolicy, null);

        HttpsURLConnection.setDefaultSSLSocketFactory(sslContext
                .getSocketFactory());
        HttpsURLConnection.setDefaultHostnameVerifier(hv);
    } catch (Exception ex) {
        return null;
    }

    URL url;
    URLConnection conn;
    try {
        url = new URL(uri);
        conn = url.openConnection();
    } catch (MalformedURLException e) {
        return null;
    } catch (IOException e) {
        return null;
    }

    return conn;
}

А это новый, использующий HttpClient:

public class HttpC2Connection {

public static HttpEntity CreateHttpEntityFromP12(String uri,
        String keyFilePath, String keyPass) throws Exception {

    KeyStore keyStore = KeyStore.getInstance("PKCS12");
    keyStore.load(new FileInputStream(keyFilePath), keyPass.toCharArray());

    SSLSocketFactory sf = new MySSLSocketFactory(keyStore);
    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("https", sf, 443));

    ClientConnectionManager ccm = new ThreadSafeClientConnManager(params,
            registry);

    HttpClient httpclient = new DefaultHttpClient(ccm, params);
    HttpGet httpget = new HttpGet(uri);
    HttpResponse response = httpclient.execute(httpget);
    HttpEntity entity = response.getEntity();

    return entity;
}

Но теперь,используя HttpClient, мой сервер возвращает мне сообщение об ошибке, в котором говорится, что я должен передать сертификат, поэтому я предполагаю, что

SSLSocketFactory sf = new MySSLSocketFactory(keyStore); 

не загружает мой сертификат.

Итак, как я могу сделатьследующие две вещи одновременно:

1.) Передать сертификат на мой сервер;2.) Принять любой сертификат с моего сервера

Используя класс HttpClient?

PS: Я использую Android 3.0

Спасибо

Ответы [ 2 ]

2 голосов
/ 05 апреля 2015

Следующий код отключает проверку сертификата SSL для любых новых экземпляров HttpsUrlConnection:

https://gist.github.com/aembleton/889392

/**
 * 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() {
        public X509Certificate[] getAcceptedIssuers() {
            return null;
        }

        @Override
        public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
            // Not implemented
        }

        @Override
        public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
            // Not implemented
        }
    } };

    try {
        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();
    }
}
0 голосов
/ 28 сентября 2011

Не просто примите любые сертификаты. Не используйте домашние SSLSocketFactory, которые ставят под угрозу безопасность.Используйте SSLSocketFactory из SDK и передайте как хранилище доверенных сертификатов (содержащее сертификат сервера или сертификат CA, который его выдал), так и хранилище ключей (содержащее ваш сертификат клиента и закрытый ключ).Для этого вы можете использовать конструктор this , в JavaDoc есть подробности о том, как создавать хранилища ключей.

...