Self-signed certificate and loopj for Android

前端 未结 6 434
太阳男子
太阳男子 2021-01-30 15:08

I\'m trying to use loopj for making async HTTP requests. Works great, except when I try to access https site with self-signed cert. I get

相关标签:
6条回答
  • 2021-01-30 15:37

    With Https and certificate I have done it successfully with the help of two docs HttpsUrlConnection and Portecle.

    0 讨论(0)
  • 2021-01-30 15:39

    You do it almost exactly the same as explained here for HttpClient except a little bit simpler - Trusting all certificates using HttpClient over HTTPS

    Create a custom class:

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

    Then when you create your client instance:

    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) {   
        }
    
    0 讨论(0)
  • 2021-01-30 15:49

    Simpler way is to use built-in MySSLSocketFactory in loopj, so you don't have to create another class

    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) {}
    
    0 讨论(0)
  • 2021-01-30 15:57

    You can use constructor AsyncHttpClient(boolean fixNoHttpResponseException, int httpPort, int httpsPort). From version loopj library 1.4.4 and bigger. For example

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

    and you get warning message to logcat at the Verbose log.

    Beware! Using the fix is insecure, as it doesn't verify SSL certificates.
    
    0 讨论(0)
  • 2021-01-30 16:01

    As explained in many places simply bypassing verification of the certificates is wrong on so many levels. Do not do that!

    What you should do instead is to create .bks file from your cert(for that purpose you gonna need 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
    

    Next place your newly created outputname.bks inside res/raw folder.

    Create helper function(it could be inside own class or whatever you like):

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

    And last but not least, set your AsyncHttpClient to use the new socket factory:

    AsyncHttpClient client = new AsyncHttpClient();
    client.setSSLSocketFactory(getSocketFactory(context));
    
    0 讨论(0)
  • 2021-01-30 16:01

    Don't NUKE all SSL certificates.. Trusting all certificates is a BAD PRACTICE!!!

    • Accept only your SSL certificate.

    Take a look at my solution. Some contents from this Gist can help your to figure how to do this.

    OBS.: I'm using Android Volley.

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

    0 讨论(0)
提交回复
热议问题