在 Android 中通过 HttpClient 重用 SSL 会话
我在使用 HttpClient 在 Android 上恢复 SSL 会话时遇到很多困难。
我每 90 秒轮询一次服务器(仅适用于具有一种功能的工业设备),因此我需要恢复会话,否则数据使用量会从每小时几 kB 飙升至 150-200kB,这是不可持续的。该服务器在 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 对象。
我在这里做错了什么!?任何人,请帮忙!
I'm having a lot of difficulty resuming an SSL session on Android using HttpClient.
I'm polling a server every 90 seconds (it's for industrial devices with one function only), so I need to resume the session or else data use skyrockets from a few kB an hour up to 150-200kB, which is unsustainable. The server is embedded Jetty in Restlet, and supports resumption of SSL sessions when I test it using OpenSSL as far as I can tell.
I'm reusing my HttpClient object, so it's not that. Android has a specific SSLCertificateSocketFactory which I've also tried and it also doesn't seem to work.
Is there something I'm completely missing here? I had presumed HttpClient would do this automatically, I'm not sure what I'm doing wrong, and no-one on the internet seems to be coming up against a similar problem.
I've set up the httpClient via:
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;
}
}
(I'm using port 444 on purpose)
Then just I reuse the HttpClient object using a simple HttpGet and Basic authorization.
What am I doing wrong here !? Anyone, please help !
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
它是固定的。它现在使用会话并消耗少量数据。
删除该行可以修复它,尽管 HttpClient 甚至从未使用过 http/port 80。我不知道为什么会这样。
It's fixed. It is now using sessions and consuming minute amounts of data.
Removing that line fixes it, despite HttpClient never even using http/port 80. Why this works I have no idea.