2013-07-29 3 views
4

Я использую статический HttpClient, и он работает очень медленно по https. Я добавил -Djavax.net.debug = ssl и обнаружил, что квитирование начинается для каждого запроса https. похоже, что он не может повторно использовать старую сессию, но я не могу найти причину.HttpClient: ssl рукопожатие по каждому запросу

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 

BTW. прежде чем я столкнулся с другой проблемой на этом хосте: "Получено фатальное предупреждение: bad_record_mac", она была решена, позволяя только SSLv3

UPD1: HttpClient INIT код

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 ("Received фатальным предупреждение: bad_record_mac»выпуск)

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 работает отлично

+0

Просьба отправить код о том, как вы выполняете запросы в http-клиенте. – drvdijk

+0

Я добавил код инициализации HttpClient, чем я просто вызываю httpClient.execute(), url всегда такой же – John

ответ

2

HttpClient повторно использует постоянный SSL connecti с проверкой подлинности клиента, только если он может убедиться, что они принадлежат к одному и тому же контексту пользователя/безопасности (по понятным причинам).

Убедитесь, что вы используете тот же самый HttpContext для всех логически связанных запросов. Это обеспечит распространение принципала безопасности (DN сертификата клиента) между отдельными HTTP-запросами.

Последующая деятельность

Он отключился сервер просто не хочет, чтобы соединения, которые будут использоваться повторно. Каждый ответ содержит директиву 'Connection: close', которая побуждает клиента закрыть соединения после получения ответа. Однако может случиться так, что сервер обрабатывает разные клиенты по-разному на основе композиции сообщения запроса. Попробуйте маскировать HttpClient, используя другое значение заголовка User-Agent и посмотрите, не имеет значения.

+0

Я попытался создать статический HttpContext и указать его каждый раз, когда я вызываю httpClient.execute(). BTW Эта проблема возникает только с 1 сервером. – John

+0

Я был бы удивлен, если бы HttpClient или HttpContext имели к этому какое-то отношение. Поддержка SSL-сеанса происходит на уровне SSLSocket, а не на уровне HTTP. – EJP

+0

@EJP: Поверьте, это так. HttpClient рассматривает SSL-соединения с аутентификацией клиента как состояния и использует контекст для распространения этого состояния – oleg

0

Как вы заявляете в комментарии о том, что проблема возникает только с одним сервером, очевидно, проблема на этом сервере. Они установили очень короткий тайм-аут сеанса SSL или вообще отключили возобновление сеанса.

С этим вы ничего не можете поделать.

+0

C# HttpSimpleClientProtocol отлично работает с этим сервером, поэтому я думаю, что можно «исправить» Java HttpClient – John

+0

Он работает с HTTPS? – EJP

+0

, как я вижу в Fiddler, он работает с https – John

Смежные вопросы