10

使用此网络库:

https://github.com/koush/ion

由于当前状态是开发,我想使用自签名 SSL 证书

图书馆论坛有一些讨论:

https://github.com/koush/ion/issues/3

 Ion ion = Ion.getDefault(c);
    ion.configure().createSSLContext("TLS");
    ion.getHttpClient().getSSLSocketMiddleware().setSSLContext(sslContext);
    ion.getHttpClient().getSSLSocketMiddleware().setTrustManagers(trustManagers);

经过一番研究,我抓住了crt并获得了sslContext和trustmanager,问题是,它仍然返回异常

javax.net.ssl.SSLException
Caused by: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.

这是我的尝试:

    try {
        CertificateFactory cf = CertificateFactory.getInstance("X.509");
        InputStream caInput = getResources().openRawResource(R.raw.load);
        Certificate ca;
        try {
            ca = cf.generateCertificate(caInput);
            //System.out.println("ca=" + ((X509Certificate) ca).getSubjectDN());
        } finally {
            caInput.close();
        }

        String keyStoreType = KeyStore.getDefaultType();
        KeyStore keyStore = KeyStore.getInstance(keyStoreType);
        keyStore.load(null, null);
        keyStore.setCertificateEntry("ca", ca);

        String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
        tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
        tmf.init(keyStore);

        ssl_context = SSLContext.getInstance("TLS");
        ssl_context.init(null, tmf.getTrustManagers(), null);
    } catch (Exception e) {
        Log.d("test1", "A: " + e);
    }

    Ion.getDefault(this).getHttpClient().getSSLSocketMiddleware().setTrustManagers(tmf.getTrustManagers());
    Ion.getDefault(this).getHttpClient().getSSLSocketMiddleware().setSSLContext(ssl_context);

    //test SSL
    Ion.getDefault(this).with(this)
            .load("https://na2b.no-ip.com/dragonair/can_app/api/media_list.php")
            .asJsonObject()
            .setCallback(new FutureCallback<JsonObject>() {
                @Override
                public void onCompleted(Exception e, JsonObject result) {
                    if (e != null) {
                        Log.d("test1", "B: " + e);
                    } else {
                        Log.d("test1", "result" + result);
                    }
                }
            });

请注意异常在 B: 部分,这意味着 trustmanager 和 SSLcontext 应该正确构建,如何解决这个问题?

感谢您的帮助。

4

4 回答 4

9

对于您的问题,IMO,您可以参考我的以下示例代码。我已经用我的网络服务(Asp.Net WebAPI)进行了测试。希望能帮助到你!

public class MainActivity extends AppCompatActivity {

    private Context mContext = this;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        try {
            CertificateFactory cf = CertificateFactory.getInstance("X.509");
            // cert file stored in \app\src\main\res\raw
            InputStream caInput = getResources().openRawResource(R.raw.your_cert);

            Certificate ca = cf.generateCertificate(caInput);
            caInput.close();

            KeyStore keyStore = KeyStore.getInstance("BKS");
            keyStore.load(null, null);
            keyStore.setCertificateEntry("ca", ca);

            String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
            TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
            tmf.init(keyStore);

            TrustManager[] wrappedTrustManagers = getWrappedTrustManagers(tmf.getTrustManagers());

            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(null, wrappedTrustManagers, null);

            AsyncSSLSocketMiddleware sslMiddleWare = Ion.getDefault(mContext).getHttpClient().getSSLSocketMiddleware();
            sslMiddleWare.setTrustManagers(wrappedTrustManagers);
            sslMiddleWare.setHostnameVerifier(getHostnameVerifier());
            sslMiddleWare.setSSLContext(sslContext);

            // Post application/x-www-form-urlencoded and read a String
            Ion.with(mContext)
                    .load("https://yourserver/token")
                    .setBodyParameter("grant_type", "password")
                    .setBodyParameter("username", "bnk")
                    .setBodyParameter("password", "bnk123456789")
                    .asString()
                    .setCallback(new FutureCallback<String>() {
                        @Override
                        public void onCompleted(Exception e, String result) {
                            if (result != null) {
                                Log.i("ionSample", result);
                            } else if (e != null) {
                                e.printStackTrace();
                            }
                        }
                    });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private HostnameVerifier getHostnameVerifier() {
        return new HostnameVerifier() {
            @Override
            public boolean verify(String hostname, SSLSession session) {
                return true;
                // or the following:
                // HostnameVerifier hv = HttpsURLConnection.getDefaultHostnameVerifier();
                // return hv.verify("www.yourserver.com", session);
            }
        };
    }

    private TrustManager[] getWrappedTrustManagers(TrustManager[] trustManagers) {
        final X509TrustManager originalTrustManager = (X509TrustManager) trustManagers[0];
        return new TrustManager[]{
                new X509TrustManager() {
                    public X509Certificate[] getAcceptedIssuers() {
                        return originalTrustManager.getAcceptedIssuers();
                    }

                    public void checkClientTrusted(X509Certificate[] certs, String authType) {
                        try {
                            if (certs != null && certs.length > 0){
                                certs[0].checkValidity();
                            } else {
                                originalTrustManager.checkClientTrusted(certs, authType);
                            }
                        } catch (CertificateException e) {
                            Log.w("checkClientTrusted", e.toString());
                        }
                    }

                    public void checkServerTrusted(X509Certificate[] certs, String authType) {
                        try {
                            if (certs != null && certs.length > 0){
                                certs[0].checkValidity();
                            } else {
                                originalTrustManager.checkServerTrusted(certs, authType);
                            }
                        } catch (CertificateException e) {
                            Log.w("checkServerTrusted", e.toString());
                        }
                    }
                }
        };
    }   
}

日志输出:

I/ionSample: {"access_token":"oS1SHxck8TzidTL...P-_6VFjRlDsjF9_A0JONu59rzYOVQV...ka78pHSvRPB5YrrBlHsF562Ay__Jd0MDfpOB0SRML2N8O3XPZK8woV4vjASzfGEzi7KJMmY8pkM_-P9ohHhWPD3PtgRahiqTUSapdpg6n197uJxdQWyU","token_type":"bearer","expires_in":2591999,"userName":"bnk",".issued":"Wed, 06 Jan 2016 06:26:45 GMT",".expires":"Fri, 05 Feb 2016 06:26:45 GMT"}
于 2016-01-06T06:31:24.177 回答
3

由于当前状态是开发,我想忽略 SSL 检查,而不是将 https 替换为 http

使用DeleteBackspace或等效操作shttpsURL 中的方案中删除 。完毕。

这假设您的服务器支持纯 HTTP。如果没有,请与维护服务器的人员交谈。

之前有绕过 SSL 检查(使用自签名证书)的经验吗?

自签名 SSL 证书不用于“绕过 SSL 检查”。如果您要连接到使用自签名证书的 HTTPS 服务器,配置 Ion(或其他 HTTP 客户端)以识别该证书。

https://您通过不请求URL 并拥有支持纯http://URL的服务器来“绕过 SSL 检查” 。

问题是如何构造 sslContext obj/信任管理器?

如果您实际上有一个使用自签名 SSL 证书的服务器,您可以使用我的 CWAC-Security 库来创建TrustManager[]. 或者,按照Nikolay Elenkov 的旧博客文章中的 Java 片段,调整它们以与 Ion 一起使用。

于 2016-01-05T11:46:11.387 回答
2
1. Generate the self signed certificate by openssl libarary.
http://stackoverflow.com/questions/10175812/how-to-create-a-self-signed-certificate-with-openssl
2. Import the same certificate or its root certificate to your server(ISS or apache.
3. Use following code in client 
// Load CAs from an InputStream
// (could be from a resource or ByteArrayInputStream or ...)
CertificateFactory cf = CertificateFactory.getInstance("X.509");
// From https://www.washington.edu/itconnect/security/ca/load-der.crt
InputStream caInput = new BufferedInputStream(new FileInputStream("load-der.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("https://certs.cac.washington.edu/CAtest/");
HttpsURLConnection urlConnection =
    (HttpsURLConnection)url.openConnection();
urlConnection.setSSLSocketFactory(context.getSocketFactory());
InputStream in = urlConnection.getInputStream();
copyInputStreamToOutputStream(in, System.out);

http://developer.android.com/training/articles/security-ssl.html
于 2016-01-06T03:54:30.720 回答
0
try {
            TrustManager[] wrappedTrustManagers = new TrustManager[]{
                    new X509TrustManager() {
                        public void checkClientTrusted(X509Certificate[] chain, String authType) {
                        }

                        public void checkServerTrusted(X509Certificate[] chain, String authType) {
                        }

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

            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(null, wrappedTrustManagers, null);

            AsyncSSLSocketMiddleware sslMiddleWare = Ion.getDefault(this).getHttpClient().getSSLSocketMiddleware();
            sslMiddleWare.setTrustManagers(wrappedTrustManagers);
            sslMiddleWare.setHostnameVerifier(new HostnameVerifier() {
                public boolean verify(String hostname, SSLSession session) {
                    return true;
                }
            });
            sslMiddleWare.setSSLContext(sslContext);

            Ion.with(this)
                    .load("https://yoururl")
                    .setBodyParameter("key1", "value1")
                    .setBodyParameter("key2", "value2")
                    .asString()
                    .setCallback(new FutureCallback<String>() {
                        @Override
                        public void onCompleted(Exception e, String result) {
                            if (result != null)
                                Log.d("responsearrived", result);

                            if (e != null) Log.d("responserror", e.toString());
                        }
                    });
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

这更危险,应该仅用于测试目的......但这有效,无需向文件系统添加证书......您提到您的项目处于开发阶段,所以这应该对您有所帮助,现在......

于 2016-07-09T21:22:08.847 回答