HttpClient: ssl handshake on every request
我使用静态HttpClient,它在https上的运行速度非常慢。我添加了-Djavax.net.debug = ssl,并发现再次为每个https请求开始握手。
看起来它无法重用旧的会话,但是我找不到原因。
1 2 3 4 5 6 7 8 9 10 11 12 | 9007199254743735, setSoTimeout(0) called Allow unsafe renegotiation: false Allow legacy hello messages: true Is initial handshake: true Is secure renegotiation: false 9007199254743735, setSoTimeout(0) called %% No cached client session *** ClientHello, SSLv3 ... %% Didn't cache non-resumable client session: [Session-1, SSL_RSA_WITH_RC4_128_MD5] ... Is initial handshake: true |
顺便说一句。在此主机上遇到另一个问题:"收到致命警报:bad_record_mac"之前,仅允许使用SSLv3
UPD1:HttpClient初始化代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | final SSLContext sslCtx; sslCtx = SSLContext.getInstance("SSL"); sslCtx.init(null, new TrustManager[]{new X509TrustManager() { @Override public void checkClientTrusted(X509Certificate[] cert, String authType) { } @Override public void checkServerTrusted(X509Certificate[] cert, String authType) { } @Override public X509Certificate[] getAcceptedIssuers() { return null; } }}, null); X509HostnameVerifier verifier = new X509HostnameVerifier() { @Override public void verify(String string, SSLSocket ssls) throws IOException { } @Override public void verify(String string, X509Certificate xc) throws SSLException { } @Override public void verify(String string, String[] strings, String[] strings1) throws SSLException { } @Override public boolean verify(String string, SSLSession ssls) { return true; } }; final SSLSocketFactory socketFactory = new SSLv3SocketFactory(sslCtx, verifier); final SchemeRegistry registry = new SchemeRegistry(); registry.register(new Scheme("https", 443, socketFactory)); final PoolingClientConnectionManager cm = new PoolingClientConnectionManager(registry); cm.setMaxTotal(100); cm.setDefaultMaxPerRoute(50); final HttpParams httpParams = new BasicHttpParams(); HttpConnectionParams.setSoTimeout(httpParams, timeout); httpClient = new DefaultHttpClient(cm, httpParams); ((DefaultHttpClient) httpClient).setKeepAliveStrategy(new ConnectionKeepAliveStrategy() { @Override public long getKeepAliveDuration(HttpResponse hr, HttpContext hc) { return 0; } }); httpClient.getParams().setParameter("http.socket.timeout", 900000); |
UPD2:修改过的SSLSocketFactory("收到的致命警报:bad_record_mac"问题)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | public class SSLv3SocketFactory extends SSLSocketFactory { private final javax.net.ssl.SSLSocketFactory socketfactory; public SSLv3SocketFactory(SSLContext sslContext, X509HostnameVerifier hostnameVerifier) { super(sslContext, hostnameVerifier); this.socketfactory = sslContext.getSocketFactory(); } @Override public Socket createLayeredSocket( final Socket socket, final String host, final int port, final boolean autoClose) throws IOException, UnknownHostException { SSLSocket sslSocket = (SSLSocket) this.socketfactory.createSocket( socket, host, port, autoClose); sslSocket.setEnabledProtocols(new String[]{"SSLv3"}); return sslSocket; } @Override public Socket connectSocket( final Socket socket, final InetSocketAddress remoteAddress, final InetSocketAddress localAddress, final HttpParams params) throws IOException, UnknownHostException, ConnectTimeoutException { if (socket instanceof SSLSocket) { ((SSLSocket) socket).setEnabledProtocols(new String[]{"SSLv3"});; } return super.connectSocket(socket, remoteAddress, localAddress, params); } } |
UPD3:仅SSLv3存在问题,TLSv1正常工作
HttpClient仅在可以确保它们属于同一用户/安全上下文(出于明显的原因)的情况下,才使用具有客户端身份验证的持久SSL连接。
确保所有逻辑相关的请求都使用相同的
跟进
它调出了服务器,只是不想重复使用连接。每个响应都包含
当您在注释中指出该问题仅发生在一台服务器上时,显然问题出在该服务器上。他们设置了非常短的SSL会话超时,或者完全禁用了会话恢复。
从一开始您就无能为力。