如何在Http代理中使用HttpClientBuilder?

job*_*bin 11 java proxy http squid

我正在尝试为我正在使用的请求设置代理,HttpClientBuilder如下所示:

        CredentialsProvider credsProvider = new BasicCredentialsProvider();
        UsernamePasswordCredentials usernamePasswordCredentials = new UsernamePasswordCredentials(proxyUser, proxyPassword);
        credsProvider.setCredentials(new AuthScope(proxyHost, proxyPort), usernamePasswordCredentials);

        builder.useSystemProperties();
        builder.setProxy(new HttpHost(proxyHost, proxyPort));
        builder.setDefaultCredentialsProvider(credsProvider);
        builder.setProxyAuthenticationStrategy(new ProxyAuthenticationStrategy());
Run Code Online (Sandbox Code Playgroud)

建造者是:

    HttpClientBuilder builder = HttpClientBuilder.create();
Run Code Online (Sandbox Code Playgroud)

但是,当我执行此请求时,我收到此异常:

java.lang.RuntimeException: org.apache.http.conn.UnsupportedSchemeException: http protocol is not supported
Caused by: org.apache.http.conn.UnsupportedSchemeException: http protocol is not supported
        at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:108) ~[httpclient-4.5.1.jar:4.5.1]
        at org.apache.http.impl.conn.BasicHttpClientConnectionManager.connect(BasicHttpClientConnectionManager.java:338) ~[httpclient-4.5.1.jar:4.5.1]
        at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:388) ~[httpclient-4.5.1.jar:4.5.1]
        at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:236) ~[httpclient-4.5.1.jar:4.5.1]
        at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:184) ~[httpclient-4.5.1.jar:4.5.1]
        at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:88) ~[httpclient-4.5.1.jar:4.5.1]
        at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110) ~[httpclient-4.5.1.jar:4.5.1]
        at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184) ~[httpclient-4.5.1.jar:4.5.1]
        at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82) ~[httpclient-4.5.1.jar:4.5.1]
        at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:107) ~[httpclient-4.5.1.jar:4.5.1]
        at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:55) ~[httpclient-4.5.1.jar:4.5.1]
Run Code Online (Sandbox Code Playgroud)

(简洁缩短除外)

由于这是一个HTTP代理,我不想将方案更改为HTTPS,这无论如何都无法工作.我该如何工作?

Sky*_*ker 16

java.lang.RuntimeException:org.apache.http.conn.UnsupportedSchemeException:不支持http协议

为什么会出现此问题?

答:这实际上是因为you forget to register a connection socket factory for the 'http' scheme.

'http'在使用'https'隧道之前,必须使用普通方案来建立与代理本身的中间连接.


出于操作目的,您可以尝试以下代码:

CloseableHttpClient client = HttpClients.custom()
           .setRoutePlanner(new
 SystemDefaultRoutePlanner(ProxySelector.getDefault()))
           .build();
Run Code Online (Sandbox Code Playgroud)

我还建议你的研究使用简单的代码.希望它能救你.

ClientExecuteProxy.java

package org.apache.http.examples.client;

import org.apache.http.HttpHost;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

/**
 * How to send a request via proxy.
 *
 * @since 4.0
 */
public class ClientExecuteProxy {

    public static void main(String[] args)throws Exception {
        CloseableHttpClient httpclient = HttpClients.createDefault();
        try {
            HttpHost target = new HttpHost("httpbin.org", 443, "https");
            HttpHost proxy = new HttpHost("127.0.0.1", 8080, "http");

            RequestConfig config = RequestConfig.custom()
                    .setProxy(proxy)
                    .build();
            HttpGet request = new HttpGet("/");
            request.setConfig(config);

            System.out.println("Executing request " + request.getRequestLine() + " to " + target + " via " + proxy);

            CloseableHttpResponse response = httpclient.execute(target, request);
            try {
                System.out.println("----------------------------------------");
                System.out.println(response.getStatusLine());
                System.out.println(EntityUtils.toString(response.getEntity()));
            } finally {
                response.close();
            }
        } finally {
            httpclient.close();
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

您是否正在使用CloudantClient Java API for Cloudant DB?

答:

如果是,那么在设置代理时,结果是HTTP的问题在我们的结尾是一个错误(抱歉).我们released 1.2.1解决了这个问题.你可以从这里下载jar文件.(收录自迈克 - 罗德斯的回答)


UPDATE

如何在此处指定代理的凭据?

HTTP身份验证,

默认情况下,httpclient不会抢先提供凭据it will first create a HTTP request without authentication parameters.这是设计,作为安全预防措施,并作为规范的一部分.但是,如果您不重试连接,或者您要连接的任何地方都希望您在第一个连接上发送身份验证详细信息,则会导致问题.它还会导致请求的额外延迟,因为您需要进行多次调用,并导致401s出现在日志中.

解决方法是使用身份验证缓存假装您已连接到服务器一次.这意味着您只能进行一次HTTP呼叫.

CloseableHttpClient httpclient = HttpClientBuilder.create().build();

HttpHost targetHost = new HttpHost("localhost", 80, "http");
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(
        new AuthScope(targetHost.getHostName(), targetHost.getPort()),
        new UsernamePasswordCredentials("username", "password"));

// Create AuthCache instance
AuthCache authCache = new BasicAuthCache();
// Generate BASIC scheme object and add it to the local auth cache
BasicScheme basicAuth = new BasicScheme();
authCache.put(targetHost, basicAuth);

// Add AuthCache to the execution context
HttpClientContext context = HttpClientContext.create();
context.setCredentialsProvider(credsProvider);
context.setAuthCache(authCache);

HttpGet httpget = new HttpGet("/");
for (int i = 0; i < 3; i++) {
    CloseableHttpResponse response = httpclient.execute(
            targetHost, httpget, context);
    try {
        HttpEntity entity = response.getEntity();

    } finally {
        response.close();
    }
}
Run Code Online (Sandbox Code Playgroud)

注意:您需要信任您正在连接的主机,如果您使用的是HTTP,您的用户名和密码将以明文形式发送(嗯,base64,但不计算在内).

你也应该使用一个更具体的Authscope而不是依赖AuthScope.ANY_HOSTAuthScope.ANY_PORT喜欢你的榜样.

信用卡去了Cetra

相关链接:

  1. HttpClientBuilder基本身份验证
  2. Apache HttpClient 4.1 - 代理验证


Joe*_*oeG 6

你所拥有的应该非常接近工作。我会做以下简单的改变:

builder.useSystemProperties();
Run Code Online (Sandbox Code Playgroud)

删除对 useSystemProperties 的调用。它没有很好地记录,但是当您设置代理时(就像您在下一行中所做的那样),它会覆盖它,因此只需删除该行。

builder.setProxy(new HttpHost(proxyHost, proxyPort));
Run Code Online (Sandbox Code Playgroud)

使用显式“方案”参数调用 HttpHost 构造函数。这是您收到错误的地方,因此请明确说明:

String proxyScheme = "http";
builder.setProxy(new HttpHost(proxyHost, proxyPort, proxyScheme));
Run Code Online (Sandbox Code Playgroud)

注意:你没有说,但根据“BasicCredentialsProvider”的用法,这只是给你“基本”身份验证。Basic 仅经过编码,并不真正安全。对于 Digest 或 NTLM 或 Kerberos,您将需要不同的代码。


小智 2

我认为问题出在你的 HttpClient 上,而不是代理上。您是否尝试使用 HttpClientBuilder.build() 创建 HttpClient

HttpClient client = builder.build();
Run Code Online (Sandbox Code Playgroud)