6

私は、自己実装した Java Web プロキシ (実際の Web サービスに要求を転送する) と Android アプリケーションの間で安全な Web サービスを開発しています。

標準の (安全でない) http 接続でこれを行うと、完全にうまく機能します。ここで、プロキシと Android クライアントの間で安全な (SSL) 接続を使用したいと考えています。

これは、リクエストごとに新しい HttpClient をインスタンス化する限り機能します。これは、リクエストごとに双方向のハンドシェイクを行っているため、リソースの浪費が非常に遅くなります。

したがって、次の例外で安全な接続が得られる各リクエストに対して HttpClient を再利用しようとしています

java.lang.IllegalStateException: 接続はすでに開いています。org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:150) で org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119) で 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.AbstractHttpClient.execute(AbstractHttpClient) .java:487) org.apache.http.impl.client.AbstractHttpClient.execute(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();
4

2 に答える 2

3

私はAndroidとHttpClientでこれとまったく同じ問題を抱えています-それはあなたが持っているのと同じように、クライアント側の証明書を使用するときにのみ現れるようです。クライアント認証を削除すると正常に動作しますが、現時点では回避策は見つかりませんでした。

編集:

古い接続チェックを有効にします。

HttpConnectionParams.setStaleCheckingEnabled(params、true);

私のためにそれを修正しました。

于 2012-11-19T07:38:06.630 に答える
0

スレッドセーフな接続マネージャーを使用していますか? そうでない場合、複数のスレッドで同じ HttpClient を使用している場合、それが問題になる可能性があります。

この記事に詳細があります: http://candrews.integralblue.com/2011/09/best-way-to-use-httpclient-in-android/

于 2012-09-21T13:54:15.020 に答える