Доверяйте всем сертификатам, используя HttpClient over HTTPS

Недавно опубликовал вопрос о HttpClient над HttpClient ( найденный здесь ). Я добился определенного прогресса, но у меня появились новые проблемы. Как и в моей последней проблеме, я не могу найти пример где-нибудь, что работает для меня. В принципе, я хочу, чтобы мой клиент принял любой сертификат (потому что я только указываю на один сервер), но я продолжаю получать 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.(PKIXParameters.java:89) W/System.err( 901): at org.apache.harmony.xnet.provider.jsse.TrustManagerImpl.(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.(SSLSocketFactory.java:190) W/System.err( 901): at org.apache.http.conn.ssl.SSLSocketFactory.(SSLSocketFactory.java:216) W/System.err( 901): at me.harrisonlee.test.ssl.MainActivity.connect(MainActivity.java:107) W/System.err( 901): ... 2 more 

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

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

В пути HttpClient вы должны создать собственный class из 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(); } } 

и использовать этот class при создании экземпляра 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(); } } 

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

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

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

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

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

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

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

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

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

 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 . Это будет показано ниже.

Выполните команду для извлечения сертификата с сервера и создания файла 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 x509TrustManagers = new ArrayList(); protected AdditionalKeyStoresTrustManager(KeyStore... additionalkeyStores) { final ArrayList factories = new ArrayList(); 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 list = new ArrayList(); for( X509TrustManager tm : x509TrustManagers ) list.addAll(Arrays.asList(tm.getAcceptedIssuers())); return list.toArray(new X509Certificate[list.size()]); } } } 

Добавьте этот код до 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(); } } 

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

Это плохая идея. Доверие к любому сертификату только (очень) немного лучше, чем использование 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(); 

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

Вы можете отключить 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()); } 

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

Код выше в 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, чтобы добавить это исправление. Прислушайся к моему предупреждению!

Я добавляю ответ для тех, кто использует 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); } } } 

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

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

  2. Загрузите Truststore из /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()); 

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

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

Я смотрю ответ от «emmby» (ответил 16.06.2011 в 21:29), item # 4: «Создайте собственный SSLSocketFactory, который использует встроенный сертификат KeyStore, но возвращается к альтернативному KeyStore для чего-то, что не работает для подтверждения по умолчанию. ”

Это упрощенная реализация. Загрузите систему keystore & merge с помощью хранилища приложений.

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

A simple mode to convert from JKS to 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 

*Note: In Android 4.0 (ICS) the Trust Store has changed, more info: http://nelenkov.blogspot.com.es/2011/12/ics-trust-store-implementation.html

For those who would like to allow all certificates to work (for testing purposes) over OAuth, follow these steps:

1) Download the source code of the Android OAuth API here: https://github.com/kaeppler/signpost

2) Find the file “CommonsHttpOAuthProvider” class

3) Change it as below:

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

The “MySSLSocketFactory” above is based on the accepted answer. To make it even easier, here goes the complete class:

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

}

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

I used this and It works for me on all OS.

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

Any body still struggling with StartCom SSL Certificates on Android 2.1 visit https://www.startssl.com/certs/ and download the ca.pem, now in the answer provided by @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` 

Should work out of the box. I was struggling it for over a day even after a perfect answer by @emmby .. Hope this helps someone...

Just adding -Dtrust_all_cert=true to VM arguments should do. This argument tells java to ignore certificate checks.

use this class

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

}

work with all 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)); 

There a many answers above but I wasn’t able to get any of them working correctly (with my limited time), so for anyone else in the same situation you can try the code below which worked perfectly for my java testing purposes:

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

and call like:

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

Reference: http://tech.chitgoks.com/2011/04/24/how-to-avoid-javax-net-ssl-sslpeerunverifiedexception-peer-not-authenticated-problem-using-apache-httpclient/

Simply use this –

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

Daniel’s answer was good except I had to change this code…

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

to this code…

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

to get it to work.

  • Простой Java HTTPS-сервер
  • Сколько информации может видеть мой интернет-провайдер?
  • Установка SSL на сервере Wamp: ошибка в httpd-ssl.conf
  • Предупреждение о подтверждении SSL: ошибка unrecognized_name с момента обновления до версии 1.7.7
  • Игнорирование сертификата SSL в Apache HttpClient 4.3
  • Могут ли клиенты telnet или netcat связываться через SSL?
  • Как я могу использовать WCF только с базовыми атрибутами, SSL и базовой аутентификацией в IIS?
  • Определение данных сертификата TLS с помощью Microsoft Edge
  • Какие Cipher Suites включить для SSL Socket?
  • Правильное закрытие SSLSocket
  • Подключение SSL / Сброс соединения с помощью IISExpress
  • Interesting Posts

    Как восстановить информацию с мертвого жесткого диска?

    Удалить и заменить Печатные элементы

    Какова цель Лупера и как его использовать?

    Работа с несколькими книгами в Excel 2013

    Что такое овеществление?

    Показать свойства навигационного свойства в DataGridView (свойства второго уровня)

    Как установить значок панели задач приложения в Windows 7

    Как написать незакодированный Json для моего представления с помощью Razor?

    Почему функции scala ограничены 22 параметрами?

    На Android сделайте запрос POST с данными URL-кодированной формы без использования UrlEncodedFormEntity

    Пять равных столбцов в twitter bootstrap

    Хранение зашифрованных данных в Postgres

    Почему unsigned int 0xFFFFFFFF равно int -1?

    Данные Spring jpa- Определен бит bean с именем ‘entityManagerFactory’; Инъекция автоуведомленных зависимостей не удалась

    TNS-12505: TNS: слушатель в настоящее время не знает о SID, заданном в дескрипторе соединения

    Давайте будем гением компьютера.