使用 HttpClient 在 Android 中重用 SSL 会话

Posted

技术标签:

【中文标题】使用 HttpClient 在 Android 中重用 SSL 会话【英文标题】:Reusing SSL Sessions in Android with HttpClient 【发布时间】:2011-08-04 08:41:38 【问题描述】:

我在使用 HttpClient 在 android 上恢复 SSL 会话时遇到了很多困难。

我每 90 秒轮询一次服务器(它仅适用于具有一个功能的工业设备),因此我需要恢复会话,否则数据使用量会从每小时几 kB 飙升至 150-200 kB,这是不可持续的.该服务器在 Restlet 中嵌入了 Jetty,据我所知,当我使用 OpenSSL 对其进行测试时,它支持恢复 SSL 会话。

我正在重用我的 HttpClient 对象,所以不是这样。 Android 有一个特定的 SSLCertificateSocketFactory,我也尝试过,但它似乎也不起作用。

这里有什么我完全想念的吗?我曾假设 HttpClient 会自动执行此操作,但我不确定我做错了什么,而且互联网上似乎没有人遇到类似的问题。

我已经通过以下方式设置了 httpClient:

    public HttpClient getNewHttpClient(Context context) 
    try 

        HttpParams params = new BasicHttpParams();
        HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
        HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);
        HttpConnectionParams.setStaleCheckingEnabled(params, false);

        HttpConnectionParams.setConnectionTimeout(params, 4 * 1000);
        HttpConnectionParams.setSoTimeout(params, 5 * 1000);
        HttpConnectionParams.setSocketBufferSize(params, 8192);

        HttpClientParams.setRedirecting(params, false);

        SSLSessionCache sslSession = new SSLSessionCache(context);
        SchemeRegistry registry = new SchemeRegistry();

        registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
        registry.register(new Scheme("https", SSLCertificateSocketFactory.getHttpSocketFactory(10*60*1000, sslSession), 444));
        //registry.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 444));

        ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry);

        return new DelegateHttpClient(ccm, params);

     catch (Exception e) 
        return new DefaultHttpClient();
    


private static class DelegateHttpClient extends DefaultHttpClient 

    private DelegateHttpClient(ClientConnectionManager ccm, HttpParams params) 
      super(ccm, params);
    

    @Override
    protected HttpContext createHttpContext() 

      HttpContext context = new BasicHttpContext();
      context.setAttribute(ClientContext.AUTHSCHEME_REGISTRY, getAuthSchemes());
      context.setAttribute(ClientContext.COOKIESPEC_REGISTRY, getCookieSpecs());
      context.setAttribute(ClientContext.CREDS_PROVIDER, getCredentialsProvider());

      CookieStore cookieStore = new BasicCookieStore(); // Create a local instance of cookie store
      context.setAttribute(ClientContext.COOKIE_STORE, cookieStore);

      return context;
    
  

(我故意使用端口 444)

然后我只需使用简单的 HttpGet 和基本授权重用 HttpClient 对象。

我在这里做错了什么!?任何人,请帮助!

【问题讨论】:

return new DefaultHttpClient(ccm, params); -- 那应该是new DelegateHttpClient吗? 啊,是的,我已经搞砸了很多年,修复了 OP - 不过这不是问题 【参考方案1】:

已经解决了。它现在正在使用会话并消耗微量数据。

registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));

尽管 HttpClient 甚至从未使用过 http/port 80,但删除该行可以修复它。我不知道为什么会这样。

【讨论】:

注:我还需要切换到简单连接器 - Jetty 似乎不适用于会话。

以上是关于使用 HttpClient 在 Android 中重用 SSL 会话的主要内容,如果未能解决你的问题,请参考以下文章

android 中HttpClient和URLConnection的区别

如何在 Android 中使用 HTTPClient 以 JSON 格式发送 POST 请求?

在 Android 中使用带有 post 参数的 HttpClient 和 HttpPost

Android 6.0 使用 Apache HttpClient

Android studio 中想用 HttpClient 下载网络图片,却没有 HttpClient 以及相关的类

如何在 Android 和/或 Java 中使用 HttpClient 管理 cookie?