Самозаверяющий сертификат и loopj для Android

Я пытаюсь использовать loopj для создания асинхронных HTTP запросов. Отлично работает, за исключением случаев, когда я пытаюсь получить доступ к сайту https с самозаверяющим сертификатом. я получил

 javax.net.ssl.SSLPeerUnverifiedException: No peer certificate. 

Я думаю, что параметры ssl по умолчанию могут быть переопределены с помощью setSSLSocketFactory(SSLSocketFactory sslSocketFactory) , но я не уверен, как это сделать, или это может быть совсем не так.

Пожалуйста, предложите, как я могу решить эту проблему?

Solutions Collecting From Web of "Самозаверяющий сертификат и loopj для Android"

Вы делаете это почти точно так же, как описано здесь для HttpClient, за исключением немного проще – доверять всем сертификатам с использованием HttpClient через HTTPS

Создайте собственный класс:

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

Затем, когда вы создаете свой экземпляр клиента:

 try { KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); trustStore.load(null, null); sf = new MySSLSocketFactory(trustStore); sf.setHostnameVerifier(MySSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); client.setSSLSocketFactory(sf); } catch (Exception e) { } 

Вы можете использовать конструктор AsyncHttpClient (boolean fixNoHttpResponseException, int httpPort, int httpsPort). Из версии loopj библиотека 1.4.4 и больше. Например

 mClient = new AsyncHttpClient(true, 80, 443); 

И вы получите предупреждение для logcat в журнале Verbose.

 Beware! Using the fix is insecure, as it doesn't verify SSL certificates. 

Простым способом является использование встроенного MySSLSocketFactory в loopj, поэтому вам не нужно создавать другой класс

 try { KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); trustStore.load(null, null); MySSLSocketFactory sf = new MySSLSocketFactory(trustStore); sf.setHostnameVerifier(MySSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); client.setSSLSocketFactory(sf); } catch (Exception e) {} 

Как объяснялось во многих местах, просто обход проверки сертификатов неверен на многих уровнях. Не делай этого!

Вместо этого вам следует создать файл .bks из вашего сертификата (для этого вам понадобится Bouncy Castle ):

 keytool -importcert -v -trustcacerts -file "path/to/certfile/certfile.crt" -alias IntermediateCA -keystore "outputname.bks" -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath "path/to/bouncycastle/bcprov-jdk15on-154.jar" -storetype BKS -storepass atleastsix 

Затем поместите вновь созданный outputname.bks внутри папки res/raw .

Создайте вспомогательную функцию (она может быть внутри собственного класса или что угодно):

 private static SSLSocketFactory getSocketFactory(Context ctx) { try { // Get an instance of the Bouncy Castle KeyStore format KeyStore trusted = KeyStore.getInstance("BKS"); // Get the raw resource, which contains the keystore with // your trusted certificates (root and any intermediate certs) InputStream in = ctx.getResources().openRawResource(R.raw.outputname); //name of your keystore file here try { // Initialize the keystore with the provided trusted certificates // Provide the password of the keystore trusted.load(in, "atleastsix".toCharArray()); } finally { in.close(); } // Pass the keystore to the SSLSocketFactory. The factory is responsible // for the verification of the server certificate. SSLSocketFactory sf = new SSLSocketFactory(trusted); // Hostname verification from certificate // http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html#d4e506 sf.setHostnameVerifier(SSLSocketFactory.STRICT_HOSTNAME_VERIFIER); // This can be changed to less stricter verifiers, according to need return sf; } catch (Exception e) { throw new AssertionError(e); } } 

И последнее, но не менее важное: установите для AsyncHttpClient новую фабрику сокетов:

 AsyncHttpClient client = new AsyncHttpClient(); client.setSSLSocketFactory(getSocketFactory(context)); 

С помощью Https и certificate я успешно справился с помощью двух документов HttpsUrlConnection и Portecle .

Не НАПРЯЖИТЕ все SSL-сертификаты. Доверяя всем сертификатам, это БЕСПЛАТНАЯ ПРАКТИКА !!!

  • Примите только ваш сертификат SSL.

Взгляните на мое решение. Некоторое содержимое этого Gist может помочь вам понять, как это сделать.

OBS .: Я использую Android Volley .

https://gist.github.com/ivanlmj/f11fb50d35fa1f2b9698bfb06aedcbcd