2014-03-12 122 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连接,它将无法查看内容。 –