Setup AsyncHttpClient to use HTTPS

前端 未结 3 723
一整个雨季
一整个雨季 2020-12-05 06:27

I am using com.loopj.android:android-async-http:1.4.9 for my request to server. It was working fine until I SSL/TLS is required in my server. So I need to modif

相关标签:
3条回答
  • 2020-12-05 06:28

    I assume you have a self signed certificate on your server, I dont have a code that does it using com.loopj.android:android-async-http:1.4.9, but I can give you code that uses URLConnection and which loads crt file (my.server.net.crt) from assets folder.:

      public static HttpsURLConnection connectSelfSignedHttps(Context ctx, String surl) throws CertificateException, IOException, KeyStoreException, NoSuchAlgorithmException, KeyManagementException {
    
        // Load CAs from an InputStream
        // (could be from a resource or ByteArrayInputStream or ...)
        CertificateFactory cf = CertificateFactory.getInstance("X.509");
    
        // 
        InputStream caInput = new BufferedInputStream(ctx.getApplicationContext().getAssets().open("my.server.net.crt"));
        Certificate ca;
        try {
          ca = cf.generateCertificate(caInput);
          //System.out.println("ca=" + ((X509Certificate) ca).getSubjectDN());
        } finally {
          caInput.close();
        }
    
        // Create a KeyStore containing our trusted CAs
        String keyStoreType = KeyStore.getDefaultType();
        KeyStore keyStore = KeyStore.getInstance(keyStoreType);
        keyStore.load(null, null);
        keyStore.setCertificateEntry("ca", ca);
    
        // Create a TrustManager that trusts the CAs in our KeyStore
        String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
        tmf.init(keyStore);
    
        // Create an SSLContext that uses our TrustManager
        SSLContext context = SSLContext.getInstance("TLS");
        context.init(null, tmf.getTrustManagers(), null);
    
        // Tell the URLConnection to use a SocketFactory from our SSLContext
        URL url = new URL(surl);
        HttpsURLConnection urlConnection =
            (HttpsURLConnection)url.openConnection();
        urlConnection.setSSLSocketFactory(context.getSocketFactory());
    
        return urlConnection;
      }
    
    0 讨论(0)
  • 2020-12-05 06:38

    As you can see here, setSSLFactory requires an object of SSLFactory, so you can create your own MySSLFactory class. In the below example I have renamed it to MyCustomSSLFactory. The code for SSL Validaton is in the method checkServerTrusted of X509TrustManager. You can modify it as per your need if needed.

    import java.io.BufferedInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.net.Socket;
    import java.security.KeyManagementException;
    import java.security.KeyStore;
    import java.security.KeyStoreException;
    import java.security.NoSuchAlgorithmException;
    import java.security.UnrecoverableKeyException;
    import java.security.cert.Certificate;
    import java.security.cert.CertificateException;
    import java.security.cert.CertificateFactory;
    import java.security.cert.X509Certificate;
    
    import javax.net.ssl.HttpsURLConnection;
    import javax.net.ssl.SSLContext;
    import javax.net.ssl.TrustManager;
    import javax.net.ssl.X509TrustManager;
    
    import cz.msebera.android.httpclient.HttpVersion;
    import cz.msebera.android.httpclient.conn.ClientConnectionManager;
    import cz.msebera.android.httpclient.conn.scheme.PlainSocketFactory;
    import cz.msebera.android.httpclient.conn.scheme.Scheme;
    import cz.msebera.android.httpclient.conn.scheme.SchemeRegistry;
    import cz.msebera.android.httpclient.conn.ssl.SSLSocketFactory;
    import cz.msebera.android.httpclient.impl.client.DefaultHttpClient;
    import cz.msebera.android.httpclient.impl.conn.tsccm.ThreadSafeClientConnManager;
    import cz.msebera.android.httpclient.params.BasicHttpParams;
    import cz.msebera.android.httpclient.params.HttpParams;
    import cz.msebera.android.httpclient.params.HttpProtocolParams;
    import cz.msebera.android.httpclient.protocol.HTTP;
    
    
    /**
     * Created by prerak on 15/03/2017.
     */
    
    public class MyCustomSSLFactory extends SSLSocketFactory {
        final SSLContext sslContext = SSLContext.getInstance("TLS");
    
        /**
         * Creates a new SSL Socket Factory with the given KeyStore.
         *
         * @param truststore A KeyStore to create the SSL Socket Factory in context of
         * @throws NoSuchAlgorithmException  NoSuchAlgorithmException
         * @throws KeyManagementException    KeyManagementException
         * @throws KeyStoreException         KeyStoreException
         * @throws UnrecoverableKeyException UnrecoverableKeyException
         */
        public MyCustomSSLFactory(KeyStore truststore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
            super(truststore);
    
            X509TrustManager tm = new X509TrustManager() {
                public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                }
    
                public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                    try {
                        chain[0].checkValidity();
                    } catch (Exception e) {
                        throw new CertificateException("Certificate not valid or trusted.");
                    }
                }
    
                public X509Certificate[] getAcceptedIssuers() {
                    return null;
                }
            };
    
            sslContext.init(null, new TrustManager[]{tm}, null);
        }
    
        /**
         * Gets a KeyStore containing the Certificate
         *
         * @param cert InputStream of the Certificate
         * @return KeyStore
         */
        public static KeyStore getKeystoreOfCA(InputStream cert) {
    
            // Load CAs from an InputStream
            InputStream caInput = null;
            Certificate ca = null;
            try {
                CertificateFactory cf = CertificateFactory.getInstance("X.509");
                caInput = new BufferedInputStream(cert);
                ca = cf.generateCertificate(caInput);
            } catch (CertificateException e1) {
                e1.printStackTrace();
            } finally {
                try {
                    if (caInput != null) {
                        caInput.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
    
            // Create a KeyStore containing our trusted CAs
            String keyStoreType = KeyStore.getDefaultType();
            KeyStore keyStore = null;
            try {
                keyStore = KeyStore.getInstance(keyStoreType);
                keyStore.load(null, null);
                keyStore.setCertificateEntry("ca", ca);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return keyStore;
        }
    
        /**
         * Gets a Default KeyStore
         *
         * @return KeyStore
         */
        public static KeyStore getKeystore() {
            KeyStore trustStore = null;
            try {
                trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
                trustStore.load(null, null);
            } catch (Throwable t) {
                t.printStackTrace();
            }
            return trustStore;
        }
    
        /**
         * Returns a SSlSocketFactory which trusts all certificates
         *
         * @return SSLSocketFactory
         */
        public static SSLSocketFactory getFixedSocketFactory() {
            SSLSocketFactory socketFactory;
            try {
                socketFactory = new MyCustomSSLFactory(getKeystore());
                socketFactory.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
            } catch (Throwable t) {
                t.printStackTrace();
                socketFactory = SSLSocketFactory.getSocketFactory();
            }
            return socketFactory;
        }
    
        /**
         * Gets a DefaultHttpClient which trusts a set of certificates specified by the KeyStore
         *
         * @param keyStore custom provided KeyStore instance
         * @return DefaultHttpClient
         */
        public static DefaultHttpClient getNewHttpClient(KeyStore keyStore) {
    
            try {
                SSLSocketFactory sf = new MyCustomSSLFactory(keyStore);
                SchemeRegistry registry = new SchemeRegistry();
                registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
                registry.register(new Scheme("https", sf, 443));
    
                HttpParams params = new BasicHttpParams();
                HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
                HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);
    
                ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry);
    
                return new DefaultHttpClient(ccm, params);
            } catch (Exception e) {
                return new DefaultHttpClient();
            }
        }
    
        @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();
        }
    
        /**
         * Makes HttpsURLConnection trusts a set of certificates specified by the KeyStore
         */
        public void fixHttpsURLConnection() {
            HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
        }
    }
    

    Now you can initialise an object of MyCustomSSLSocketFactory by passing your custom KeyStore to it.

    MyCustomSSLFactory socketFactory = new MyCustomSSLFactory(keyStore);
    

    And now you can set the socket factory as:

    asyncHTTPClient.setSSLSocketFactory(socketFactory);
    
    0 讨论(0)
  • 2020-12-05 06:38

    you can use @Prerak's solution. Looks like that solution works. This is my own version. It is similar to @Prerak's but a shorter constructor:

    public CustomSSLSocketFactory(KeyStore truststore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
        super(truststore);
    
        // Create a TrustManager that trusts the CAs in our KeyStore
        String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
        tmf.init(truststore);
    
        // Create an SSLContext that uses our TrustManager
        sslContext.init(null, tmf.getTrustManagers(), null);
    }
    
    0 讨论(0)
提交回复
热议问题