HttpRoutePlanner - 它如何与 HTTPS 代理一起工作

2024-02-09

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

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

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

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

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

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

下面的图表通过区分 HTTP 代理设置来解释我的设置 -

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 请求。然后在客户端和终端站点之间建立 SSL 隧道

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 请求应加密到代理。后续请求无论如何都会被隧道传输。

有人可以告诉我如何实现这个目标吗?我相信 HttpRoutePlanner 应该有所帮助,但我不知道如何。


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

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

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 终端站点通信,路由应该是安全的,但不应该有任何隧道或分层。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

HttpRoutePlanner - 它如何与 HTTPS 代理一起工作 的相关文章

随机推荐