我正在使用Apache Http客户端4.0.1与服务器进行通信。我已经有一个安全/非安全的客户端代码,可以正常工作。
最近新添加的是为此代码添加代理,所以我添加了以下代码来执行此操作(当前非安全代理),
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)
尝试了以下事项,
然而,在这两种情况下都失败了,
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在我的localhost上运行非安全代理。
编辑:这是我用于代理通信的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 :(得分:0)
我不知道你是在处理证书信托问题。
虽然没有看到你如何具体建立连接,但我可以毫不确定地说。
“未经过身份验证的对等体”意味着无法验证一个或多个服务器所提供的证书验证。
修改强> 由于代理权在您的控制之下,因此您目前具有很大的灵活性。
请参阅this SO article,它可能符合您的需求。