【问题标题】:SSL connection reuse with Android HttpClient使用 Android HttpClient 重用 SSL 连接
【发布时间】:2012-09-21 12:24:32
【问题描述】:

我正在我自己实现的 java web 代理(将请求转发到实际的 web 服务)和一个 android 应用程序之间开发一个安全的 web 服务。

使用标准(不安全)http 连接这样做非常有效。现在我想在代理和安卓客户端之间使用安全 (SSL) 连接。

只要我为每个请求实例化一个新的 HttpClient 就可以工作,除了浪费资源非常慢,因为我正在为每个请求进行两次握手。

所以我尝试为每个请求重用 HttpClient,这会导致以下异常中的安全连接

java.lang.IllegalStateException:连接已经打开。 在 org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:150) 在 org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119) 在 org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:360) 在 org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555) 在 org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487) 在 org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465)

当我将代理和客户端更改为无 SSL 通信时,它可以正常工作。 有人知道我做错了什么吗?非常感谢您的帮助!

顺便说一句,服务器代码完全相似,除了使用带有加载证书的 SSLServerSocket 而不是使用 ServerSocket。

客户端参数设置

// Set basic data
    HttpParams params = new BasicHttpParams();
    HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
    HttpProtocolParams.setContentCharset(params, "UTF-8");
    HttpProtocolParams.setUseExpectContinue(params, true);
    HttpProtocolParams.setUserAgent(params, "Android app/1.0.0");

    // Make pool
    ConnPerRoute connPerRoute = new ConnPerRouteBean(12);
    ConnManagerParams.setMaxConnectionsPerRoute(params, connPerRoute);
    ConnManagerParams.setMaxTotalConnections(params, 20);

    // Set timeout
    HttpConnectionParams.setStaleCheckingEnabled(params, false);
    HttpConnectionParams.setConnectionTimeout(params, connectionTimeoutMillis);
    HttpConnectionParams.setSoTimeout(params, socketTimeoutMillis);
    HttpConnectionParams.setSocketBufferSize(params, 8192);

    // Some client params
    HttpClientParams.setRedirecting(params, false);

Http客户端创建

// load truststore certificate
            InputStream clientTruststoreIs = context.getResources().openRawResource(R.raw.server);
            KeyStore trustStore = KeyStore.getInstance("BKS");
            trustStore.load(clientTruststoreIs, "server".toCharArray());

            // initialize trust manager factory with the read truststore
            TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
            trustManagerFactory.init(trustStore);

            // setup client certificate

            // load client certificate
            InputStream keyStoreStream = context.getResources().openRawResource(R.raw.client);
            KeyStore keyStore = KeyStore.getInstance("BKS");
            keyStore.load(keyStoreStream, "client".toCharArray());

            // initialize key manager factory with the read client
            // certificate
            KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
            keyManagerFactory.init(keyStore, "client".toCharArray());

            // initialize SSLSocketFactory to use the certificates
            SSLSocketFactory socketFactory = new SSLSocketFactory(SSLSocketFactory.TLS, keyStore, "client", trustStore, null, null);

            // Register http/s shemas!
            SchemeRegistry schReg = new SchemeRegistry();
            schReg.register(new Scheme("https", socketFactory, port));
            ClientConnectionManager conMgr = new ThreadSafeClientConnManager(params, schReg);

            httpClient = new DefaultHttpClient(conMgr, params);

客户端请求执行

HttpResponse response = httpClient.execute(request);
        HttpEntity entity = response.getEntity();
        in = entity.getContent();
        String result = convertStreamToString(in);
        in.close();

【问题讨论】:

    标签: android ssl httpclient


    【解决方案1】:

    我对 Android 和 HttpClient 也有同样的问题——它似乎只在使用客户端证书时才表现出来,就像你一样。删除客户端身份验证,它工作正常,还没有找到解决方法。

    编辑:

    启用失效连接检查。

    HttpConnectionParams.setStaleCheckingEnabled(params, true);

    帮我修好了。

    【讨论】:

    • 谢谢。可以确认这只发生在启用客户端证书的情况下,这也为我修复了它。
    【解决方案2】:

    您使用的是线程安全的连接管理器吗?如果不是,那可能是您在多个线程中使用相同的 HttpClient 时出现的问题。

    本文有详细信息:http://candrews.integralblue.com/2011/09/best-way-to-use-httpclient-in-android/

    【讨论】:

    • 感谢您的回答。是的,正如您在我提供的代码中看到的那样。如果我在没有 SSL 的情况下使用它,即使从不同的线程中使用,该代码也可以正常工作。但是当我更改为 SSL 时,它会因顶部的异常而中断。还有其他建议吗?
    猜你喜欢
    • 2011-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-30
    • 2013-10-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多