繁体   English   中英

Apache Http Client 4.0.1 SSL代理

[英]Apache Http Client 4.0.1 SSL Proxy

我正在使用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)

尝试了以下事情,

  1. 对于https请求,我使用与用于“ https”的SSLFactory相同的SSLFactory将“ http”和“ https”添加到架构注册表。
  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();
    }
}

谢谢,Vicky

我想说的是,您正在处理证书信任问题。

但是,在没有看到您如何具体设置连接的情况下,我无法确定地说。

“未对等身份验证”是指沿线某处无法验证由一个或多个服务器提供的证书的验证。

编辑由于代理处于您的控制之下,因此您现在拥有很大的灵活性。

请参阅这篇SO文章 ,它可能适合您的需求。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM