2012-09-21 2 views
5

저는 자체 구현 된 자바 웹 프록시 (실제 웹 서비스에 요청을 전달하는)와 안드로이드 애플리케이션 사이에 안전한 웹 서비스를 개발 중입니다.안드로이드 HttpClient와의 SSL 연결 재사용

표준 (안전하지 않은) HTTP 연결을 사용하면 완벽하게 작동합니다. 이제 프록시와 안드로이드 클라이언트 사이에 보안 (SSL) 연결을 사용하고 싶습니다.

각 요청에 대해 새로운 HttpClient를 인스턴스화하는 한 이것은 작동합니다. 이는 각 요청에 대해 양방향 핸드 셰이크를 수행 할 때 매우 느린 리소스 낭비 옆에 있습니다. 연결이 이미 열려 :

그래서 나는 다음과 같은 예외

java.lang.IllegalStateException에서 보안 연결에 대한 결과를 각 요청에 대한 HttpClient를을 재사용하기 위해 노력하고있어. at org.apache.http.impl.conn.AbstractPoolEntry.open (AbstractPoolEntry.java:150) at org.apache.http.impl.conn.AbstractPooledConnAdapter.open (AbstractPooledConnAdapter.java:119) at org.apache. http.impl.client.DefaultRequestDirector.execute (DefaultRequestDirector.java:360) at org.apache.http.impl.client.AbstractHttpClient.execute (AbstractHttpClient.java:555) at org.apache.http.impl.client. org.apache.http.impl.client.AbstractHttpClient.execute에서 AbstractHttpClient.execute (AbstractHttpClient.java:487) (AbstractHttpClient.java:465)

내가없는 SSL 내 프록시 클라이언트를 변경

통신은 문제없이 작동합니다. 누구도 내가 뭘 잘못하고 있는지 알아? 도와 주셔서 정말로 고맙습니다!

그런데 서버 코드는 ServerSocket 대신에로드 된 인증서가있는 SSLServerSocket을 사용하는 것을 제외하면 완전히 유사합니다.

클라이언트 파라미터 설정

// 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(); 

답변

0

당신이 스레드 안전 연결 관리자를 사용하고 있습니까? 그렇지 않다면 여러 스레드에서 동일한 HttpClient를 사용하는 경우 문제가 될 수 있습니다. http://candrews.integralblue.com/2011/09/best-way-to-use-httpclient-in-android/

+0

답변 해 주셔서 감사합니다. 네, 제가 제공 한 코드에서 알 수 있듯이 그렇게합니다. 다른 스레드에서 사용하는 경우에도 SSL없이 사용하면 코드가 완벽하게 작동합니다. 하지만 SSL로 변경하면 맨 위에 예외가 발생합니다. 다른 제안? – user1033552

3

나는 안드로이드와 HttpClient를이 동일한 문제를 가지고 - 당신이처럼 클라이언트 측 인증서를 사용하는 경우에만 명시 할 것 같다 :

이 문서에서는 세부 사항이있다. 클라이언트 인증을 제거하면 제대로 작동하지만 아직 해결 방법을 찾지 못했습니다.

편집 :

부실 연결 검사를 사용합니다.

HttpConnectionParams.setStaleCheckingEnabled (params, true);

저를 위해 고쳐졌습니다.

+0

Thx. 이 문제는 클라이언트 인증서가 활성화 된 경우에만 발생하는 것으로 확인할 수 있습니다. – icyerasor