HttpRoutePlanner - 它如何与 HTTPS 代理一起工作 [英] HttpRoutePlanner - How does it work with an HTTPS Proxy

查看:34
本文介绍了HttpRoutePlanner - 它如何与 HTTPS 代理一起工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我设置了 HTTPS 代理,以便 HTTP 客户端可以安全地向代理发送纯 HTTP 请求.例如,客户端可以向代理发送加密的 HTTP GET 请求,代理将删除加密并将纯 HTTP GET 请求发送到终端站点.

I have an HTTPS proxy set up so that HTTP clients can send plain HTTP requests securely to the proxy. For example, a client can send an encrypted HTTP GET request to the proxy, which will remove the encryption and send the plain HTTP GET request to the end-site.

我了解到这不是一个常见的设置,只有 Google Chrome 具有支持这种情况的内置功能.(这里的信息 - http://wiki.squid-cache.org/Features/HTTPS#Encrypted_browser-Squid_connection).我已经让谷歌浏览器与我的 HTTPS 代理一起工作,因此代理端没有问题.

I learned that this is not a common set up and only Google Chrome has in-built features to support such a scenario. (Info here - http://wiki.squid-cache.org/Features/HTTPS#Encrypted_browser-Squid_connection). I have made Google Chrome work with my HTTPS proxy and hence there is no trouble on the proxy side.

我希望编写一个 HTTP 客户端来加密对我的 HTTPS 代理的所有请求.我尝试以这种方式将 HTTPS 代理设置为 DefaultHttpClient -

I wish to write an HTTP Client that will encrypt all requests to my HTTPS Proxy. I tried setting an HTTPS proxy to DefaultHttpClient this way -

DefaultHttpClient dhc = new DefaultHttpClient();
HttpHost proxy = new HttpHost("192.168.2.3", 8181, "https"); //NOTE : https
dhc.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy);

然后尝试执行任何请求都会给我一个 SSLPeerUnverifiedException.我不明白为什么.

Then trying to execute any request gives me an SSLPeerUnverifiedException. I do not understand the reason why.

在探索 DefaultHttpClient API 期间,我遇到了 HttpRoutePlanner 和 HttpRoute,我们可以使用它们来指定是否应加密与代理的连接.但是,我无法完成这项工作.

During my exploration of the DefaultHttpClient API, I came across HttpRoutePlanner and HttpRoute with which we can specify whether the connection to proxies should be encrypted or not. However, I am unable to make this work.

这是一个图表,通过将它与 HTTP 代理设置区分开来解释我的设置 -

Here is a diagram that explains my setup by differentiating it with a HTTP Proxy setup -

HTTP 代理:

HTTP Client <------- Plain Text GET, POST Requests -------> HTTP Proxy <------- Plain Text GET, POST Requests -------> HTTP End-Site

HTTP Client <------- Plain Text CONNECT Requests -------> HTTP Proxy <------- Plain Text CONNECT Requests -------> HTTPS End-Site

注意:对于 HTTPS 终端站点,代理只能看到 CONNECT 请求.然后在Client和End-Site之间建立SSL隧道

NOTE: For HTTPS End-Sites, only the CONNECT Request is seen by the proxy. Then an SSL Tunnel is established between the Client and End-Site

HTTPS 代理:

HTTP Client <------- Encrypted GET, POST Requests -------> HTTPS Proxy <-------- Plain Text GET, POST Requests -------->  HTTP End-Site

HTTP Client <------- Encrypted CONNECT Requests -------> HTTPS Proxy <------- Plain Text CONNECT Requests -------> HTTPS End-Site

注意:对于 HTTPS 终端站点,仅应对代理加密初始 CONNECT 请求.无论如何,后续请求都将通过隧道传输.

NOTE: For HTTPS End-Sites, only the initial CONNECT Request should be encrypted to the proxy. The subsequent request will anyway be tunnelled.

谁能告诉我如何实现这个目标?我相信 HttpRoutePlanner 应该会有所帮助,但我不知道如何.

Can anybody please let me know how I can achieve this goal? I believe HttpRoutePlanner should help, but I don't know how.

推荐答案

我能够让 Apache HttpClient 4.x 与 HTTPS 代理一起工作.我在问题中提到的 SSLPeerUnverifiedException 被抛出,因为我不信任代理服务器的证书.一旦解决了这个问题,到 HTTPS 终端站点的连接就会按预期工作.

I was able to make the Apache HttpClient 4.x work with the HTTPS proxy. The SSLPeerUnverifiedException that I mentioned in the question was thrown because I was not trusting the Proxy Server's certificate. Once this is taken care of, then connections to HTTPS End-Sites worked as expected.

对于到 HTTP 终端站点的连接,我必须使用我自己的 HttpRoutePlanner 使其工作.这是带有解释的代码 -

For connections to HTTP end-sites, I had to use my own HttpRoutePlanner to make it work. Here's the code with the explanations -

DefaultHttpClient dhc = new DefaultHttpClient();
HttpHost proxy = new HttpHost("192.168.2.3", 8181, "https");
dhc.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy);

SchemeSocketFactory factory = null;
try {
    factory = new SSLSocketFactory(new SimpleTrustStrategy()); //Trust All strategy
} catch (GeneralSecurityException e1) {
    e1.printStackTrace();
}
Scheme https = new Scheme("https", 443, factory);
dhc.getConnectionManager().getSchemeRegistry().register(https);

HttpGet request = new HttpGet("http://en.wikipedia.org/wiki/Main_Page");    

try {
    HttpHost host = determineTarget(request);

    if(host.getSchemeName().equalsIgnoreCase("http")){
        dhc.setRoutePlanner(new MyRoutePlanner());
    }

} catch (ClientProtocolException e1) {
    e1.printStackTrace();
}

MyRoutePlanner 的实现如下 -

public class MyRoutePlanner implements HttpRoutePlanner {
    @Override
    public HttpRoute determineRoute(HttpHost target, HttpRequest request,
            HttpContext context) throws HttpException {
        return new HttpRoute(target, null
                , new HttpHost("192.168.2.3", 8181, "https")
                , true, TunnelType.PLAIN, LayerType.PLAIN); //Note: true
    }
}

为了让 HttpClient 通过 HTTPS 代理与 HTTP 终端站点通信,路由应该是安全的,但不应该有任何隧道或分层.

To make the HttpClient talk to a HTTP End-site through an HTTPS Proxy, the route should be secure, but there should not be any Tunnelling or Layering.

这篇关于HttpRoutePlanner - 它如何与 HTTPS 代理一起工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆