2014-03-12 210 views
0

我正在使用Apache Http客戶端4.0.1與服務器進行通信。我已經有一個安全/不安全的客戶端代碼,工作得很好。Apache Http客戶端4.0.1 SSL代理

最近新增加的是到代理添加到這個代碼,所以我說了以下一段代碼來做到這一點(目前非安全代理),

HttpHost proxy = new HttpHost("localhost", 5555); 
httpClient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy); 

這一直很好用非安全性的要求。但是,我在使用相同代碼的安全(https)請求時遇到問題。

獲得以下異常(它會嘗試一些時間失效之前),

Mar 12, 2014 11:14:27 AM org.apache.http.impl.client.DefaultRequestDirector tryConnect 
INFO: I/O exception (org.apache.http.NoHttpResponseException) caught when connecting to the target host: The target server failed to respond 
Mar 12, 2014 11:14:27 AM org.apache.http.impl.client.DefaultRequestDirector tryConnect 
INFO: Retrying connect 
org.apache.http.NoHttpResponseException: The target server failed to respond 
    at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:95) 
    at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:62) 
    at org.apache.http.impl.io.AbstractMessageParser.parse(AbstractMessageParser.java:254) 
    at org.apache.http.impl.AbstractHttpClientConnection.receiveResponseHeader(AbstractHttpClientConnection.java:289) 
    at org.apache.http.impl.conn.DefaultClientConnection.receiveResponseHeader(DefaultClientConnection.java:252) 
    at org.apache.http.impl.conn.ManagedClientConnectionImpl.receiveResponseHeader(ManagedClientConnectionImpl.java:191) 
    at org.apache.http.protocol.HttpRequestExecutor.doReceiveResponse(HttpRequestExecutor.java:300) 
    at org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:127) 
    at org.apache.http.impl.client.DefaultRequestDirector.createTunnelToTarget(DefaultRequestDirector.java:899) 
    at org.apache.http.impl.client.DefaultRequestDirector.establishRoute(DefaultRequestDirector.java:818) 
    at org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:644) 
    at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:479) 
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:906) 
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:805) 
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:784) 
    at com.poc.test.SSLTest.main(SSLTest.java:88) 

嘗試下面的東西,

  1. HTTPS請求,我加入這兩個 「HTTP」 以及「HTTPS 「到模式註冊表,使用與用於」https「的SSLFactory相同的SSLFactory。
  2. 將代理更改爲, HttpHost proxy = new HttpHost(「localhost」,5555,「https」);

然而,在這兩種情況下它與失敗,

javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated 
    at sun.security.ssl.SSLSessionImpl.getPeerCertificates(SSLSessionImpl.java:397) 
    at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:128) 
    at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:572) 
    at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:180) 
    at org.apache.http.impl.conn.ManagedClientConnectionImpl.open(ManagedClientConnectionImpl.java:294) 
    at org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:640) 
    at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:479) 
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:906) 
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:805) 
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:784) 
    at com.poc.test.SSLTest.main(SSLTest.java:89) 

注 - 我正在上通過TCPMON我的本地非安全代理。

編輯:這裏是我使用與代理通信的SSL的代碼,

DefaultHttpClient httpClient = new DefaultHttpClient(); 

try { 
    SSLContext ctx = SSLContext.getInstance("TLSv1.1"); 
    TrustManager[] trustManagers = getTrustManagers("jks", new FileInputStream(new File("C:\\SSLKeyStore.ks")), "changeit"); 
    ctx.init(null, trustManagers, new SecureRandom()); 

    HttpGet httpget = new HttpGet("https://localhost:8844/Channels/HTTP/getData"); 
    System.out.println("executing request" + httpget.getRequestLine()); 

    SSLSocketFactory factory = new SSLSocketFactory(ctx); 
    factory.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); 

    ClientConnectionManager manager = httpClient.getConnectionManager(); 
    manager.getSchemeRegistry().register(new Scheme("https", 443, factory)); 
    manager.getSchemeRegistry().register(new Scheme("http", 80, PlainSocketFactory.getSocketFactory())); 

    HttpHost proxy = new HttpHost("localhost", 5555, "http"); 
    httpClient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy); 

    HttpResponse response = httpClient.execute(httpget); 
    HttpEntity entity = response.getEntity(); 

    System.out.println("----------------------------------------"); 
    System.out.println(response.getStatusLine()); 
    if (entity != null) { 
     System.out.println("Response content length: " + entity.getContentLength()); 
    } 
    EntityUtils.consume(entity); 
} catch (Exception exception) { 
    exception.printStackTrace(); 
} finally { 
    httpClient.getConnectionManager().shutdown(); 
} 

正在發生什麼的任何想法,我是相對於HTTPS和代理錯過了什麼。

最新編輯 - 甚至嘗試他們的示例代碼(ClientExecuteProxy.java)原樣,代理也失敗了。這個功能是否被破壞?

HttpHost proxy = new HttpHost("127.0.0.1", 8080, "http"); 

    DefaultHttpClient httpclient = new DefaultHttpClient(); 
    try { 
     httpclient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy); 

     HttpHost target = new HttpHost("issues.apache.org", 443, "https"); 
     HttpGet req = new HttpGet("/"); 

     System.out.println("executing request to " + target + " via " + proxy); 
     HttpResponse rsp = httpclient.execute(target, req); 
     HttpEntity entity = rsp.getEntity(); 

     System.out.println("----------------------------------------"); 
     System.out.println(rsp.getStatusLine()); 
     Header[] headers = rsp.getAllHeaders(); 
     for (int i = 0; i<headers.length; i++) { 
      System.out.println(headers[i]); 
     } 
     System.out.println("----------------------------------------"); 

     if (entity != null) { 
      System.out.println(EntityUtils.toString(entity)); 
     } 

    } finally { 
     // When HttpClient instance is no longer needed, 
     // shut down the connection manager to ensure 
     // immediate deallocation of all system resources 
     httpclient.getConnectionManager().shutdown(); 
    } 
} 

感謝, 玉萍

+0

人們,沒有人使用過/在這工作?我會在Apache論壇上發佈這個。希望有人能提供一些指導。 – Vicky

回答

0

關閉我的頭頂,我會說,你是在處理一個證書信任問題。

沒有看到你如何設置連接,我可以毫不猶豫地說。

「未通過身份驗證」意味着沿線某處由一個或多個服務器提供的證書驗證無法驗證。

編輯 由於代理服務器在您的控制之下,因此您現在有一定的靈活性。

請參閱this SO article,它可能適合您的需求。

+0

是的,我有一個不安全的代理通過tcpmon運行,所以不需要真正的安全檢查。如果我刪除代理片段,則該通話成功完成。 – Vicky

+0

已經檢查過以前的帖子,但無法找到我的代碼和[鏈接]中提到的代碼之間的區別(http://stackoverflow.com/questions/8580479/apache-httpclient-able-to-communicate-over- https-when-direct-but-not-via-proxy-e) – Vicky

+0

確定你發佈的編輯 - 如果你正在代理https-over-http我看不到tcpmon如何能夠確定內容請求。您已將目標主機作爲localhost/5555/http - 您將通過它發送加密數據。不管你是否配置了tcpmon的代理來終止和退出SSL連接,它將無法查看內容。 –