Доверие всем сертификатам с использованием HttpClient через HTTPS


393

Недавно выложили вопрос по поводу HttpClientсверх https ( находится здесь ). Я добился определенных успехов, но столкнулся с новыми проблемами. Как и с моей последней проблемой, я не могу найти пример где-нибудь, что работает для меня. По сути, я хочу, чтобы мой клиент принял любой сертификат (потому что я указываю только на один сервер), но я продолжаю получатьjavax.net.ssl.SSLException: Not trusted server certificate exception.

Итак, вот что я имею:


    public void connect() throws A_WHOLE_BUNCH_OF_EXCEPTIONS {

        HttpPost post = new HttpPost(new URI(PROD_URL));
        post.setEntity(new StringEntity(BODY));

        KeyStore trusted = KeyStore.getInstance("BKS");
        trusted.load(null, "".toCharArray());
        SSLSocketFactory sslf = new SSLSocketFactory(trusted);
        sslf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

        SchemeRegistry schemeRegistry = new SchemeRegistry();
        schemeRegistry.register(new Scheme ("https", sslf, 443));
        SingleClientConnManager cm = new SingleClientConnManager(post.getParams(),
                schemeRegistry);

        HttpClient client = new DefaultHttpClient(cm, post.getParams());
        HttpResponse result = client.execute(post);
    }

И вот ошибка, которую я получаю:

    W/System.err(  901): javax.net.ssl.SSLException: Not trusted server certificate 
    W/System.err(  901):    at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:360) 
    W/System.err(  901):    at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:92) 
    W/System.err(  901):    at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:321) 
    W/System.err(  901):    at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:129) 
    W/System.err(  901):    at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164) 
    W/System.err(  901):    at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119) 
    W/System.err(  901):    at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:348) 
    W/System.err(  901):    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555) 
    W/System.err(  901):    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487) 
    W/System.err(  901):    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465) 
    W/System.err(  901):    at me.harrisonlee.test.ssl.MainActivity.connect(MainActivity.java:129) 
    W/System.err(  901):    at me.harrisonlee.test.ssl.MainActivity.access$0(MainActivity.java:77) 
    W/System.err(  901):    at me.harrisonlee.test.ssl.MainActivity$2.run(MainActivity.java:49) 
    W/System.err(  901): Caused by: java.security.cert.CertificateException: java.security.InvalidAlgorithmParameterException: the trust anchors set is empty 
    W/System.err(  901):    at org.apache.harmony.xnet.provider.jsse.TrustManagerImpl.checkServerTrusted(TrustManagerImpl.java:157) 
    W/System.err(  901):    at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:355) 
    W/System.err(  901):    ... 12 more 
    W/System.err(  901): Caused by: java.security.InvalidAlgorithmParameterException: the trust anchors set is empty 
    W/System.err(  901):    at java.security.cert.PKIXParameters.checkTrustAnchors(PKIXParameters.java:645) 
    W/System.err(  901):    at java.security.cert.PKIXParameters.<init>(PKIXParameters.java:89) 
    W/System.err(  901):    at org.apache.harmony.xnet.provider.jsse.TrustManagerImpl.<init>(TrustManagerImpl.java:89) 
    W/System.err(  901):    at org.apache.harmony.xnet.provider.jsse.TrustManagerFactoryImpl.engineGetTrustManagers(TrustManagerFactoryImpl.java:134) 
    W/System.err(  901):    at javax.net.ssl.TrustManagerFactory.getTrustManagers(TrustManagerFactory.java:226)W/System.err(  901):     at org.apache.http.conn.ssl.SSLSocketFactory.createTrustManagers(SSLSocketFactory.java:263) 
    W/System.err(  901):    at org.apache.http.conn.ssl.SSLSocketFactory.<init>(SSLSocketFactory.java:190) 
    W/System.err(  901):    at org.apache.http.conn.ssl.SSLSocketFactory.<init>(SSLSocketFactory.java:216) 
    W/System.err(  901):    at me.harrisonlee.test.ssl.MainActivity.connect(MainActivity.java:107) 
    W/System.err(  901):    ... 2 more

17
Мне нужно было сделать это для внутреннего использования. Я действительно надеюсь, что вы не позволите пользователям вне вашей компании использовать ваше приложение, так как вы открыли его для человека, находящегося в середине атаки, и тогда они будут уязвимы для кого-то, кто захватывает их сеанс. тем не менее, мне нужно сделать это временно для некоторого тестирования, пока я не получу настоящий сертификат в руках ... надеюсь, вы делаете это по той же временной причине или приложение используется только для внутреннего использования.
Дин Хиллер

Я попробовал эти решения на 4,3 Apache HTTP-клиент, но они в основном устарели. Вот не осуждаемое решение: stackoverflow.com/a/18941950/2039471
Александр Чжен

Java 1.6 не имеет поддержки SNI, что также проблематично в этих сценариях - если вы не создадите запрос должным образом, вы можете получить сертификат, который не соответствует запросу. См. Questions.apache.org/jira/browse/HTTPCLIENT-1119
Брон Дэвис

2
Этот вопрос цитируется в газете «Самый опасный кодекс в мире» как пример ошибочных рассуждений. (научно - исследовательская работа: cs.utexas.edu/~shmat/shmat_ccs12.pdf )
mk_

Ответы:


421

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

Ваш вопрос как раз то, что я хочу знать. После того, как я сделал некоторые поиски, вывод следующий.

В HttpClient вы должны создать собственный класс из org.apache.http.conn.ssl.SSLSocketFactory, а не один org.apache.http.conn.ssl.SSLSocketFactory. Некоторые подсказки можно найти в этом посте. Пользовательская обработка SSL перестала работать на Android 2.2 FroYo .

Пример как ...

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;

import org.apache.http.conn.ssl.SSLSocketFactory;
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();
    }
}

и использовать этот класс при создании экземпляра HttpClient.

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

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

Кстати, ссылка ниже предназначена для тех, кто ищет решение HttpURLConnection. HTTP-соединение Android

Я протестировал два вышеупомянутых решения на froyo, и все они работают как шарм в моих случаях. Наконец, использование HttpURLConnection может столкнуться с проблемами перенаправления, но это выходит за рамки темы.

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

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


150
этот ответ должен, вероятно, заметить, что доверять всем сертификатам ужасно небезопасно и сводит на нет всю цель ssl ...
yanokwa

22
@sweeney - За исключением того, что не гарантируется, что вы разговариваете с сервером, который вы считаете. Если кто-то взломал DNS-сервер, вы могли бы связать ключ шифрования с сервером хакера.
Ричард Сзалай

12
@sweeney Другими словами, теперь вы подвержены атакам «человек посередине». Следует также отметить, что этот код не соответствует спецификации: проверьте Javadoc. getAcceptedIssuers()не разрешено возвращать ноль.
Маркиз Лорн

25
-1 Потому что страшно принимать все сертификаты. Очень жаль, что существует так много блогов и учебных пособий, которые с радостью направляют разработчиков Java на путь неправильных действий.
Тим Бендер

57
+1 Потому что мне нужно было быстрое решение только для целей отладки. Я не стал бы использовать это в производстве из-за проблем безопасности, о которых упоминали другие, но это было именно то, что мне нужно для тестирования. Спасибо!
Данация

495

В основном у вас есть четыре возможных решения для исправления исключения «Не доверенные» на Android с использованием httpclient:

  1. Доверяй всем сертификатам. Не делайте этого, если вы действительно не знаете, что делаете.
  2. Создайте собственный SSLSocketFactory, который доверяет только вашему сертификату. Это работает до тех пор, пока вы точно знаете, к каким серверам вы собираетесь подключаться, но как только вам нужно подключиться к новому серверу с другим сертификатом SSL, вам нужно будет обновить приложение.
  3. Создайте файл хранилища ключей, который содержит «главный список» сертификатов Android, а затем добавьте свой собственный. Если срок действия какого-либо из этих сертификатов истекает, вы несете ответственность за их обновление в своем приложении. Я не могу придумать причину сделать это.
  4. Создайте пользовательский SSLSocketFactory, который использует встроенный сертификат KeyStore, но использует альтернативный KeyStore для всего, что не удается проверить по умолчанию.

В этом ответе используется решение № 4, которое мне кажется наиболее надежным.

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

Сначала вы захотите определить, какой сертификат отсутствует в вашем хранилище ключей. Запустите следующую команду:

openssl s_client -connect www.yourserver.com:443

И вы увидите вывод, подобный следующему:

Certificate chain
 0 s:/O=www.yourserver.com/OU=Go to 
   https://www.thawte.com/repository/index.html/OU=Thawte SSL123 
   certificate/OU=Domain Validated/CN=www.yourserver.com
   i:/C=US/O=Thawte, Inc./OU=Domain Validated SSL/CN=Thawte DV SSL CA
 1 s:/C=US/O=Thawte, Inc./OU=Domain Validated SSL/CN=Thawte DV SSL CA
   i:/C=US/O=thawte, Inc./OU=Certification Services Division/OU=(c) 
   2006 thawte, Inc. - For authorized use only/CN=thawte Primary Root CA

Как видите, наш корневой сертификат от Thawte. Зайдите на сайт вашего провайдера и найдите соответствующий сертификат. Для нас это было здесь , и вы можете видеть, что нам нужен был Copyright 2006.

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

Затем создайте файл хранилища ключей, содержащий отсутствующий сертификат подписи. У Crazybob есть детали, как это сделать на Android , но идея состоит в том, чтобы сделать следующее:

Если у вас его еще нет, загрузите библиотеку поставщика надувных замков по адресу : http://www.bouncycastle.org/latest_releases.html . Это пойдет на ваш classpath ниже.

Запустите команду, чтобы извлечь сертификат с сервера и создать файл pem. В этом случае mycert.pem.

echo | openssl s_client -connect ${MY_SERVER}:443 2>&1 | \
 sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > mycert.pem

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

export CLASSPATH=/path/to/bouncycastle/bcprov-jdk15on-155.jar
CERTSTORE=res/raw/mystore.bks
if [ -a $CERTSTORE ]; then
    rm $CERTSTORE || exit 1
fi
keytool \
      -import \
      -v \
      -trustcacerts \
      -alias 0 \
      -file <(openssl x509 -in mycert.pem) \
      -keystore $CERTSTORE \
      -storetype BKS \
      -provider org.bouncycastle.jce.provider.BouncyCastleProvider \
      -providerpath /path/to/bouncycastle/bcprov-jdk15on-155.jar \
      -storepass some-password

Вы заметите, что приведенный выше скрипт помещает результат в res/raw/mystore.bks. Теперь у вас есть файл, который вы загрузите в свое приложение для Android, которое предоставляет недостающие сертификаты.

Для этого зарегистрируйте свой SSLSocketFactory для схемы SSL:

final SchemeRegistry schemeRegistry = new SchemeRegistry();
schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
schemeRegistry.register(new Scheme("https", createAdditionalCertsSSLSocketFactory(), 443));

// and then however you create your connection manager, I use ThreadSafeClientConnManager
final HttpParams params = new BasicHttpParams();
...
final ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager(params,schemeRegistry);

Чтобы создать свой SSLSocketFactory:

protected org.apache.http.conn.ssl.SSLSocketFactory createAdditionalCertsSSLSocketFactory() {
    try {
        final KeyStore ks = KeyStore.getInstance("BKS");

        // the bks file we generated above
        final InputStream in = context.getResources().openRawResource( R.raw.mystore);  
        try {
            // don't forget to put the password used above in strings.xml/mystore_password
            ks.load(in, context.getString( R.string.mystore_password ).toCharArray());
        } finally {
            in.close();
        }

        return new AdditionalKeyStoresSSLSocketFactory(ks);

    } catch( Exception e ) {
        throw new RuntimeException(e);
    }
}

И наконец, код AdditionalKeyStoresSSLSocketFactory, который принимает ваш новый KeyStore и проверяет, не удается ли встроенному KeyStore проверить сертификат SSL:

/**
 * Allows you to trust certificates from additional KeyStores in addition to
 * the default KeyStore
 */
public class AdditionalKeyStoresSSLSocketFactory extends SSLSocketFactory {
    protected SSLContext sslContext = SSLContext.getInstance("TLS");

    public AdditionalKeyStoresSSLSocketFactory(KeyStore keyStore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
        super(null, null, null, null, null, null);
        sslContext.init(null, new TrustManager[]{new AdditionalKeyStoresTrustManager(keyStore)}, null);
    }

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

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



    /**
     * Based on http://download.oracle.com/javase/1.5.0/docs/guide/security/jsse/JSSERefGuide.html#X509TrustManager
     */
    public static class AdditionalKeyStoresTrustManager implements X509TrustManager {

        protected ArrayList<X509TrustManager> x509TrustManagers = new ArrayList<X509TrustManager>();


        protected AdditionalKeyStoresTrustManager(KeyStore... additionalkeyStores) {
            final ArrayList<TrustManagerFactory> factories = new ArrayList<TrustManagerFactory>();

            try {
                // The default Trustmanager with default keystore
                final TrustManagerFactory original = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
                original.init((KeyStore) null);
                factories.add(original);

                for( KeyStore keyStore : additionalkeyStores ) {
                    final TrustManagerFactory additionalCerts = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
                    additionalCerts.init(keyStore);
                    factories.add(additionalCerts);
                }

            } catch (Exception e) {
                throw new RuntimeException(e);
            }



            /*
             * Iterate over the returned trustmanagers, and hold on
             * to any that are X509TrustManagers
             */
            for (TrustManagerFactory tmf : factories)
                for( TrustManager tm : tmf.getTrustManagers() )
                    if (tm instanceof X509TrustManager)
                        x509TrustManagers.add( (X509TrustManager)tm );


            if( x509TrustManagers.size()==0 )
                throw new RuntimeException("Couldn't find any X509TrustManagers");

        }

        /*
         * Delegate to the default trust manager.
         */
        public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            final X509TrustManager defaultX509TrustManager = x509TrustManagers.get(0);
            defaultX509TrustManager.checkClientTrusted(chain, authType);
        }

        /*
         * Loop over the trustmanagers until we find one that accepts our server
         */
        public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            for( X509TrustManager tm : x509TrustManagers ) {
                try {
                    tm.checkServerTrusted(chain,authType);
                    return;
                } catch( CertificateException e ) {
                    // ignore
                }
            }
            throw new CertificateException();
        }

        public X509Certificate[] getAcceptedIssuers() {
            final ArrayList<X509Certificate> list = new ArrayList<X509Certificate>();
            for( X509TrustManager tm : x509TrustManagers )
                list.addAll(Arrays.asList(tm.getAcceptedIssuers()));
            return list.toArray(new X509Certificate[list.size()]);
        }
    }

}

Эй, @emmby, похоже, это идеальный ответ для моей проблемы, но я все еще не получаю SSL-соединение. Можете ли вы взглянуть на это? http://stackoverflow.com/questions/7822381/need-help-understanding-certificate-chains
Матиас Б

Спасибо за отличную рецензию @emmby! Иногда я получаю очень долгую задержку, а затем javax.net.ssl.SSLException: Ошибка чтения. Есть идеи? Как установить время ожидания, если решение такое же, как stackoverflow.com/questions/5909308/android-2-3-4-ssl-problem ?
Эдвин Эванс

3
@emmby, не могли бы вы сказать, куда мне поместить этот экспорт кода CLASSPATH = bcprov-jdk16-145.jar CERTSTORE = res / raw / mystore.bks if [-a $ CERTSTORE]; тогда гм $ CERTSTORE || exit 1 fi keytool \ -import \ -v \ -trustcacerts \ -alias 0 \ -file <(openssl x509 -in mycert.pem) \ -keystore $ CERTSTORE \ -storetype BKS \ -provider org.bouncycastle.jce.provider. BouncyCastleProvider \ -providerpath /usr/share/java/bcprov.jar \ -storepass some-password
Рикки Тикки Тави,

1
Привет, @emmby. Я использую ваше решение в своем приложении и использую самозаверяющий сертификат моего сервера, но получаю CertificateException () в методе checkServerTrusted () . Я попытался прокомментировать это исключение, и оно работает. если он не проверяет мой сертификат сервера, то могу ли я обработать его другим способом, не могли бы вы подсказать, какое решение лучше всего подходит в этом случае?
Анкит

7
Это должно быть помечено как правильный ответ. Один из самых подробных и хорошо написанных ответов, которые я когда-либо видел на SO. Допинг
Качи

74

Добавьте этот код до HttpsURLConnectionи это будет сделано. Я понял.

private void trustEveryone() { 
    try { 
            HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier(){ 
                    public boolean verify(String hostname, SSLSession session) { 
                            return true; 
                    }}); 
            SSLContext context = SSLContext.getInstance("TLS"); 
            context.init(null, new X509TrustManager[]{new X509TrustManager(){ 
                    public void checkClientTrusted(X509Certificate[] chain, 
                                    String authType) throws CertificateException {} 
                    public void checkServerTrusted(X509Certificate[] chain, 
                                    String authType) throws CertificateException {} 
                    public X509Certificate[] getAcceptedIssuers() { 
                            return new X509Certificate[0]; 
                    }}}, new SecureRandom()); 
            HttpsURLConnection.setDefaultSSLSocketFactory( 
                            context.getSocketFactory()); 
    } catch (Exception e) { // should never happen 
            e.printStackTrace(); 
    } 
} 

Я надеюсь, это поможет вам.


22
См. Замечания выше под принятым ответом. Это «решение» радикально небезопасно.
Маркиз Лорн

5
Это идеальное решение для вопросов и ответов. Коротко и "просто работает".
Стив Смит,

5
Идеальный ответ для тестирования! И да, это плохая идея для использования в производстве, но давай ... это должно быть понятно всем, кто смотрит на название вопроса. Он по-прежнему отвечает лучше / короче / с тем же (не) уровнем безопасности!
Левит

34

Это плохая идея. Доверять любому сертификату только (очень) немного лучше, чем вообще не использовать SSL. Когда вы говорите: «Я хочу, чтобы мой клиент принял любой сертификат (потому что я указываю только на один сервер)», вы подразумеваете, что указание на «один сервер» каким-то образом безопасно, чего нет в общедоступной сети.

Вы полностью открыты для атаки «человек посередине», доверяя любому сертификату. Любой может прокси-соединение через ваше соединение, установив отдельное SSL-соединение с вами и с конечным сервером. MITM получает доступ ко всем вашим запросам и ответам. Если вам не нужен действительно SSL в первую очередь (ваше сообщение не имеет ничего чувствительного и не выполняет аутентификацию), вам не следует слепо доверять всем сертификатам.

Вы должны рассмотреть возможность добавления общедоступного сертификата в jks с помощью keytool и использовать его для создания фабрики сокетов, например:

    KeyStore ks = KeyStore.getInstance("JKS");

    // get user password and file input stream
    char[] password = ("mykspassword")).toCharArray();
    ClassLoader cl = this.getClass().getClassLoader();
    InputStream stream = cl.getResourceAsStream("myjks.jks");
    ks.load(stream, password);
    stream.close();

    SSLContext sc = SSLContext.getInstance("TLS");
    KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
    TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");

    kmf.init(ks, password);
    tmf.init(ks);

    sc.init(kmf.getKeyManagers(), tmf.getTrustManagers(),null);

    return sc.getSocketFactory();

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


5
Если вы не используете аутентификацию по сертификату клиента, со стороны клиента вам не нужен менеджер ключей (используйте nullв SSLContext.init). You should also use the default algorithms (KMF/TMF.getDefaultAlgorithm() ), instead of hard-coding SunX509` (тем более, что по умолчанию для TMF фактически PKIXиспользуется Sun / Oracle JVM).
Bruno

Существует готовый файл корневых сертификатов? (как это делают браузеры)
Дани Эррера

Откуда myjks.jksвзялось?
zionpi

1
@zionpi Генерируется с помощью Java "keytool".
Дан

22

Вы можете отключить проверку SSL HttpURLConnection для целей тестирования, начиная с API 8:

    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
    if (conn instanceof HttpsURLConnection) {
        HttpsURLConnection httpsConn = (HttpsURLConnection) conn;
        httpsConn.setSSLSocketFactory(SSLCertificateSocketFactory.getInsecure(0, null));
        httpsConn.setHostnameVerifier(new AllowAllHostnameVerifier());
    }

2
org.apache.http.conn.ssl.AllowAllHostnameVerifierустарел.
Закигаурав

2
@zackygaurav Согласно javadoc , AllowAllHostnameVerifierзаменяется на NoopHostnameVerifier"
DLight

10

API HttpComponents изменился. Это работает с кодом ниже.

public static HttpClient getTestHttpClient() {
    try {
        SSLSocketFactory sf = new SSLSocketFactory(new TrustStrategy(){
            @Override
            public boolean isTrusted(X509Certificate[] chain,
                    String authType) throws CertificateException {
                return true;
            }
        }, new AllowAllHostnameVerifier());

        SchemeRegistry registry = new SchemeRegistry();
        registry.register(new Scheme("https",8444, sf));
        ClientConnectionManager ccm = new ThreadSafeClientConnManager(registry);
        return new DefaultHttpClient(ccm);
    } catch (Exception e) {
        e.printStackTrace();
        return new DefaultHttpClient();
    }
}

Использование собственной стратегии доверия является правильным ответом. Спасибо.
Мэтт Фридман

10

Код выше в https://stackoverflow.com/a/6378872/1553004 правильный, за исключением того, что он ДОЛЖЕН также вызывать верификатор имени хоста:

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

Я подписался на stackoverflow специально, чтобы добавить это исправление. Обратите внимание на мое предупреждение!


Как только вы проверите сертификат при первом соединении, что вы будете делать с последующими соединениями? Используете ли вы знания, которые вы получили от первого подключения? Что если при попытке подключения 3 используется поддельный сертификат с тем же именем?
jww

6

Я добавляю ответ для тех, кто использует httpclient-4.5 и, вероятно, работает и для 4.4.

import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.HttpResponseException;
import org.apache.http.client.fluent.ContentResponseHandler;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContextBuilder;



public class HttpClientUtils{

public static HttpClient getHttpClientWithoutSslValidation_UsingHttpClient_4_5_2() {
    try {
        SSLContextBuilder builder = new SSLContextBuilder();
        builder.loadTrustMaterial(null, new TrustStrategy() {
            @Override
            public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                return true;
            }
        });
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(builder.build(), new NoopHostnameVerifier());
        CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build(); 
        return httpclient;
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}
}

что такое новый класс NoopHostnameVerifier ()?
Муштаким Ахмед Ансари

1
@MushtakimAhmedAnsari Из документов: «NO_OP HostnameVerifier по существу отключает проверку имени хоста. Эта реализация не работает и никогда не выдает исключение SSLEx».
raisercostin

Спасибо за отличный ответ. Этот должен получить больше голосов.
Абхай Двиведи

Как мне это использовать? или вы предлагаете, чтобы просто наличие класса переопределило проверки SSL-сертификатов?
бехелит

да. что httpClient при использовании не будет проверять сертификаты https
raisercostin

4

Доверие всем сертификатам не было для меня реальной альтернативой, поэтому я сделал следующее, чтобы HttpsURLConnection доверял новому сертификату (см. Также http://nelenkov.blogspot.jp/2011/12/using-custom-certificate-trust-store- on.html ).

  1. Получить сертификат; Я сделал это, экспортировав сертификат в Firefox (нажмите на маленький значок замка, получите информацию о сертификате, нажмите экспорт), а затем использовали portecle для экспорта склада доверенных сертификатов (BKS).

  2. Загрузите хранилище доверенных сертификатов из /res/raw/geotrust_cert.bks со следующим кодом:

        final KeyStore trustStore = KeyStore.getInstance("BKS");
        final InputStream in = context.getResources().openRawResource(
                R.raw.geotrust_cert);
        trustStore.load(in, null);
    
        final TrustManagerFactory tmf = TrustManagerFactory
                .getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmf.init(trustStore);
    
        final SSLContext sslCtx = SSLContext.getInstance("TLS");
        sslCtx.init(null, tmf.getTrustManagers(),
                new java.security.SecureRandom());
    
        HttpsURLConnection.setDefaultSSLSocketFactory(sslCtx
                .getSocketFactory());

Я получаю эту ошибку. IOExceptionjavax.net.ssl.SSLPeerUnverifiedException: No peer certificate, Это происходит при выполнении фактического вызова execute для HttpClient после выполнения вышеуказанной настройки.
Майкл

3

Вот очень простая версия с использованием кода httpclient 4.1.2. Затем его можно изменить на любой алгоритм доверия, который вы считаете нужным.

public static HttpClient getTestHttpClient() {
    try {
        SSLSocketFactory sf = new SSLSocketFactory(new TrustStrategy(){
            @Override
            public boolean isTrusted(X509Certificate[] chain,
                    String authType) throws CertificateException {
                return true;
            }
        });
        SchemeRegistry registry = new SchemeRegistry();
        registry.register(new Scheme("https", 443, sf));
        ClientConnectionManager ccm = new ThreadSafeClientConnManager(registry);
        return new DefaultHttpClient(ccm);
    } catch (Exception e) {
        return new DefaultHttpClient();
    }
}

3

Я посмотрел ответ от "emmby" (ответил 16 июня '11 в 21:29), пункт № 4: "Создайте собственный SSLSocketFactory, который использует встроенный сертификат KeyStore, но использует альтернативный KeyStore для всего, что дает сбой проверить по умолчанию. "

Это упрощенная реализация. Загрузите системное хранилище ключей и объедините его с хранилищем ключей приложения.

public HttpClient getNewHttpClient() {
    try {
        InputStream in = null;
        // Load default system keystore
        KeyStore trusted = KeyStore.getInstance(KeyStore.getDefaultType()); 
        try {
            in = new BufferedInputStream(new FileInputStream(System.getProperty("javax.net.ssl.trustStore"))); // Normally: "/system/etc/security/cacerts.bks"
            trusted.load(in, null); // no password is "changeit"
        } finally {
            if (in != null) {
                in.close();
                in = null;
            }
        }

        // Load application keystore & merge with system
        try {
            KeyStore appTrusted = KeyStore.getInstance("BKS"); 
            in = context.getResources().openRawResource(R.raw.mykeystore);
            appTrusted.load(in, null); // no password is "changeit"
            for (Enumeration<String> e = appTrusted.aliases(); e.hasMoreElements();) {
                final String alias = e.nextElement();
                final KeyStore.Entry entry = appTrusted.getEntry(alias, null);
                trusted.setEntry(System.currentTimeMillis() + ":" + alias, entry, null);
            }
        } finally {
            if (in != null) {
                in.close();
                in = null;
            }
        }

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

        SSLSocketFactory sf = new SSLSocketFactory(trusted);
        sf.setHostnameVerifier(SSLSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);

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

Простой режим для преобразования из JKS в BKS:

keytool -importkeystore -destkeystore cacerts.bks -deststoretype BKS -providerclass org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath bcprov-jdk16-141.jar -deststorepass changeit -srcstorepass changeit -srckeystore $JAVA_HOME/jre/lib/security/cacerts -srcstoretype JKS -noprompt

* Примечание. В Android 4.0 (ICS) изменился трастовый магазин. Дополнительная информация: http://nelenkov.blogspot.com.es/2011/12/ics-trust-store-implementation.html.


3

Для тех, кто хочет, чтобы все сертификаты работали (для целей тестирования) над OAuth, выполните следующие действия:

1) Загрузите исходный код API OAuth для Android здесь: https://github.com/kaeppler/signpost

2) Найдите файл класса "CommonsHttpOAuthProvider"

3) Измените его, как показано ниже:

public class CommonsHttpOAuthProvider extends AbstractOAuthProvider {

private static final long serialVersionUID = 1L;

private transient HttpClient httpClient;

public CommonsHttpOAuthProvider(String requestTokenEndpointUrl, String accessTokenEndpointUrl,
        String authorizationWebsiteUrl) {
    super(requestTokenEndpointUrl, accessTokenEndpointUrl, authorizationWebsiteUrl);


    //this.httpClient = new DefaultHttpClient();//Version implemented and that throws the famous "javax.net.ssl.SSLException: Not trusted server certificate" if the certificate is not signed with a CA
    this.httpClient = MySSLSocketFactory.getNewHttpClient();//This will work with all certificates (for testing purposes only)
}

«MySSLSocketFactory» выше основан на принятом ответе. Чтобы сделать это еще проще, вот полный класс:

package com.netcomps.oauth_example;

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;

import org.apache.http.HttpVersion;
import org.apache.http.client.HttpClient;
import org.apache.http.conn.ClientConnectionManager;
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.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
import org.apache.http.protocol.HTTP;

//http://stackoverflow.com/questions/2642777/trusting-all-certificates-using-httpclient-over-https
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() {

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

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

        @Override
        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 static 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();
    }
}

}

Надеюсь, это кому-нибудь поможет.


1
Вопрос был HttpClientи по HTTPS; не OAuth для Android из проекта GitHub.
jww

3

Я использовал это, и это работает для меня на всех ОС.

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

Привет @ yegor256, я использую этот код, но все еще получаю проблему рукопожатия SSL
user2028

1

Просто добавление -Dtrust_all_cert=trueв VM аргументов должно подойти. Этот аргумент говорит Java игнорировать проверки сертификатов.


4
Пожалуйста, не добавляйте один и тот же ответ на несколько вопросов. Ответьте лучшим и отметьте остальные как дубликаты. См. Допустимо ли добавить дублирующий ответ на несколько вопросов?
Петтер Фриберг

0

Любой, кто до сих пор борется с SSL-сертификатами StartCom на Android 2.1, посещает https://www.startssl.com/certs/ и скачивает ca.pem, теперь в ответе, предоставленном @emmby replace

`export CLASSPATH=bcprov-jdk16-145.jar
 CERTSTORE=res/raw/mystore.bks
      if [ -a $CERTSTORE ]; then
          rm $CERTSTORE || exit 1
      fi
 keytool \
  -import \
  -v \
  -trustcacerts \
  -alias 0 \
  -file <(openssl x509 -in mycert.pem) \
  -keystore $CERTSTORE \
  -storetype BKS \
  -provider org.bouncycastle.jce.provider.BouncyCastleProvider \
  -providerpath /usr/share/java/bcprov.jar \
  -storepass some-password`

с

 `export CLASSPATH=bcprov-jdk16-145.jar
 CERTSTORE=res/raw/mystore.bks
      if [ -a $CERTSTORE ]; then
          rm $CERTSTORE || exit 1
      fi
 keytool \
  -import \
  -v \
  -trustcacerts \
  -alias 0 \
  -file <(openssl x509 -in ca.pem) \
  -keystore $CERTSTORE \
  -storetype BKS \
  -provider org.bouncycastle.jce.provider.BouncyCastleProvider \
  -providerpath /usr/share/java/bcprov.jar \
  -storepass some-password`

Должно работать из коробки. Я боролся с этим более суток, даже после того, как @emmby дал идеальный ответ .. Надеюсь, это кому-нибудь поможет ...


0

использовать этот класс

public class WCFs
{
    //  https://192.168.30.8/myservice.svc?wsdl
private static final String NAMESPACE = "http://tempuri.org/";
private static final String URL = "192.168.30.8";
private static final String SERVICE = "/myservice.svc?wsdl";
private static String SOAP_ACTION = "http://tempuri.org/iWCFserviceMe/";


public static Thread myMethod(Runnable rp)
{
    String METHOD_NAME = "myMethod";

    SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);

    request.addProperty("Message", "Https WCF Running...");
    return _call(rp,METHOD_NAME, request);
}

protected static HandlerThread _call(final RunProcess rp,final String METHOD_NAME, SoapObject soapReq)
{
    final SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
    int TimeOut = 5*1000;

    envelope.dotNet = true;
    envelope.bodyOut = soapReq;
    envelope.setOutputSoapObject(soapReq);

    final HttpsTransportSE httpTransport_net = new HttpsTransportSE(URL, 443, SERVICE, TimeOut);

    try
    {
        HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() // use this section if crt file is handmake
        {
            @Override
            public boolean verify(String hostname, SSLSession session)
            {
                return true;
            }
        });

        KeyStore k = getFromRaw(R.raw.key, "PKCS12", "password");
        ((HttpsServiceConnectionSE) httpTransport_net.getServiceConnection()).setSSLSocketFactory(getSSLSocketFactory(k, "SSL"));


    }
    catch(Exception e){}

    HandlerThread thread = new HandlerThread("wcfTd"+ Generator.getRandomNumber())
    {
        @Override
        public void run()
        {
            Handler h = new Handler(Looper.getMainLooper());
            Object response = null;

            for(int i=0; i<4; i++)
            {
                response = send(envelope, httpTransport_net , METHOD_NAME, null);

                try
                {if(Thread.currentThread().isInterrupted()) return;}catch(Exception e){}

                if(response != null)
                    break;

                ThreadHelper.threadSleep(250);
            }

            if(response != null)
            {
                if(rp != null)
                {
                    rp.setArguments(response.toString());
                    h.post(rp);
                }
            }
            else
            {
                if(Thread.currentThread().isInterrupted())
                    return;

                if(rp != null)
                {
                    rp.setExceptionState(true);
                    h.post(rp);
                }
            }

            ThreadHelper.stopThread(this);
        }
    };

    thread.start();

    return thread;
}


private static Object send(SoapSerializationEnvelope envelope, HttpTransportSE androidHttpTransport, String METHOD_NAME, List<HeaderProperty> headerList)
{
    try
    {
        if(headerList != null)
            androidHttpTransport.call(SOAP_ACTION + METHOD_NAME, envelope, headerList);
        else
            androidHttpTransport.call(SOAP_ACTION + METHOD_NAME, envelope);

        Object res = envelope.getResponse();

        if(res instanceof SoapPrimitive)
            return (SoapPrimitive) envelope.getResponse();
        else if(res instanceof SoapObject)
            return ((SoapObject) envelope.getResponse());
    }
    catch(Exception e)
    {}

    return null;
}

public static KeyStore getFromRaw(@RawRes int id, String algorithm, String filePassword)
{
    try
    {
        InputStream inputStream = ResourceMaster.openRaw(id);
        KeyStore keystore = KeyStore.getInstance(algorithm);
        keystore.load(inputStream, filePassword.toCharArray());
        inputStream.close();

        return keystore;
    }
    catch(Exception e)
    {}

    return null;
}

public static SSLSocketFactory getSSLSocketFactory(KeyStore trustKey, String SSLAlgorithm)
{
    try
    {
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmf.init(trustKey);

        SSLContext context = SSLContext.getInstance(SSLAlgorithm);//"SSL" "TLS"
        context.init(null, tmf.getTrustManagers(), null);

        return context.getSocketFactory();
    }
    catch(Exception e){}

    return null;
}

}



-3

работать со всеми https

httpClient = new DefaultHttpClient();

SSLContext ctx = SSLContext.getInstance("TLS");
X509TrustManager tm = new X509TrustManager() {
    public void checkClientTrusted(X509Certificate[] xcs, String string) throws CertificateException { }

    public void checkServerTrusted(X509Certificate[] xcs, String string) throws CertificateException { }

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

ctx.init(null, new TrustManager[]{tm}, null);
SSLSocketFactory ssf = new SSLSocketFactory(ctx, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

httpClient.getConnectionManager().getSchemeRegistry().register(new Scheme("https", 443, ssf));

2
Просто повторяется то же ошибочное небезопасное нерешенное решение, которое уже обсуждалось и отклонялось в этой теме.
Маркиз Лорн

-3

Выше было много ответов, но я не смог заставить ни один из них работать правильно (из-за моего ограниченного времени), поэтому для всех, кто находится в такой же ситуации, вы можете попробовать приведенный ниже код, который отлично подошел для моих целей тестирования Java:

    public static HttpClient wrapClient(HttpClient base) {
    try {
        SSLContext ctx = SSLContext.getInstance("TLS");
        X509TrustManager tm = new X509TrustManager() {
            public void checkClientTrusted(X509Certificate[] xcs, String string) throws CertificateException { }

            public void checkServerTrusted(X509Certificate[] xcs, String string) throws CertificateException { }

            public X509Certificate[] getAcceptedIssuers() {
                return null;
            }
        };
        ctx.init(null, new TrustManager[]{tm}, null);
        SSLSocketFactory ssf = new SSLSocketFactory(ctx);
        ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
        ClientConnectionManager ccm = base.getConnectionManager();
        SchemeRegistry sr = ccm.getSchemeRegistry();
        sr.register(new Scheme("https", ssf, 443));
        return new DefaultHttpClient(ccm, base.getParams());
    } catch (Exception ex) {
        return null;
    }
}

и звоните как:

DefaultHttpClient baseClient = new DefaultHttpClient();
HttpClient httpClient = wrapClient(baseClient );

Ссылка: http://tech.chitgoks.com/2011/04/24/how-to-avoid-javax-net-ssl-sslpeerunverifiedexception-peer-not-authenticated-problem-using-apache-httpclient/


Процитирую EJP: «Просто повторяет то же ошибочное небезопасное нерешенное решение, которое уже обсуждалось и отклонялось в этой теме» .
jww

-4

Просто используйте это -

public DefaultHttpClient wrapClient(HttpClient base) {
    try {
        SSLContext ctx = SSLContext.getInstance("TLS");
        X509TrustManager tm = new X509TrustManager() {
        public void checkClientTrusted(X509Certificate[] xcs, String string) throws CertificateException { }

        public void checkServerTrusted(X509Certificate[] xcs, String string) throws CertificateException { }

        public X509Certificate[] getAcceptedIssuers() {
            return null;
        }
    };
    ctx.init(null, new TrustManager[]{tm}, null);
    SSLSocketFactory ssf = new SSLSocketFactory(ctx);
    ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
    ClientConnectionManager ccm = base.getConnectionManager();
    SchemeRegistry sr = ccm.getSchemeRegistry();
    sr.register(new Scheme("https", ssf, 443));
    return new DefaultHttpClient(ccm, base.getParams());
} catch (Exception ex) {
    return null;
}
}

Процитирую EJP: «Просто повторяет то же ошибочное небезопасное нерешенное решение, которое уже обсуждалось и отклонялось в этой теме» .
jww

-5

Даниэль ответил хорошо, но мне пришлось изменить этот код ...

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

к этому коду ...

    ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry);
    SchemeRegistry registry = ccm.getShemeRegistry()
    registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
    registry.register(new Scheme("https", sf, 443));

заставить его работать.


5
как это должно работать? Вы ссылаетесь на реестр еще до того, как создали его!
Матиас Б.
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.