Apache HttpClient 4.1 - 代理身份验证

31

我一直在尝试使用Apaches HttpComponent的httpclient从已配置的属性中配置代理身份验证的用户名和密码,但一直没有成功。我找到的所有示例都引用了不再可用的方法和类,例如HttpStatesetProxyCredentials

那么,有人能给我一个如何配置代理凭据的示例吗?


我们是在谈论Basic-Auth还是NTLM? - nfechner
@nfechner 我会尽力去获取任何东西。实际上,最好两者都有。 - Daniel C. Sobral
7个回答

42

对于任何正在寻找4.3版本答案的人...这是一个相对较新版本,并且它们的示例没有使用新的HttpClientBuilder...所以这是我如何在该版本中实现的:

NTCredentials ntCreds = new NTCredentials(ntUsername, ntPassword,localMachineName, domainName );

CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials( new AuthScope(proxyHost,proxyPort), ntCreds );
HttpClientBuilder clientBuilder = HttpClientBuilder.create();

clientBuilder.useSystemProperties();
clientBuilder.setProxy(new HttpHost(pxInfo.getProxyURL(), pxInfo.getProxyPort()));
clientBuilder.setDefaultCredentialsProvider(credsProvider);
clientBuilder.setProxyAuthenticationStrategy(new ProxyAuthenticationStrategy());

CloseableHttpClient client = clientBuilder.build();

27

对于Basic-Auth,它看起来像这样:

DefaultHttpClient httpclient = new DefaultHttpClient();
httpclient.getCredentialsProvider().setCredentials(
    new AuthScope("PROXY HOST", 8080),
    new UsernamePasswordCredentials("username", "password"));

HttpHost targetHost = new HttpHost("TARGET HOST", 443, "https");
HttpHost proxy = new HttpHost("PROXY HOST", 8080);

httpclient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy);

据我所知,NTLM不支持开箱即用。但是您可以尝试使用NTCredentials并可能重载DefaultProxyAuthenticationHandler来管理它。


1
如果代理设置出错或代理服务器宕机,会发生什么情况?如何处理这些情况? - Pratswinz
1
targetHost 变量不是未使用/不必要的吗? - Mahesha999
你如何确保代理在一次运行中进行多次迭代(比如100次)时总是更改IP地址? - zt1983811

19

除了NTLM以外,可以在4.3+的httpClient上使用普通的用户名和密码,如下所示:

HttpHost proxy = new HttpHost("x.x.com",8080);
Credentials credentials = new UsernamePasswordCredentials("username","password");
AuthScope authScope = new AuthScope("x.x.com", 8080);
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(authScope, credentials);
HttpClient client = HttpClientBuilder.create().setProxy(proxy).setDefaultCredentialsProvider(credsProvider).build();
HttpResponse response=client.execute(new HttpGet("https://dev59.com/NGw05IYBdhLWcg3w4125"));

3
如果我尝试在需要NTLM身份验证的代理服务器上使用UsernamePasswordCredentials,我会收到以下异常:auth.HttpAuthenticator(HttpAuthenticator.java:207)-NTLM身份验证错误:无法使用凭据进行NTLM身份验证:org.apache.http.auth.UsernamePasswordCredentials。为了解决这个问题,我使用了NTCredentials - trebor

10

如何使用Apache的httpclient设置代理服务器认证

(代理网络上的预授权)

本答案使用Apache HttpClient v4.1及以上版本。

对我来说,已有的答案行不通,但我找到了其他可行的方法!这是经过测试验证的来自Apache的代码,演示了如何通过代理进行HTTP请求身份验证。

完整文档在此处:https://hc.apache.org/httpcomponents-client-ga/tutorial/html/authentication.html

Apache还提供了一个优秀的示例:https://hc.apache.org/httpcomponents-client-ga/httpclient/examples/org/apache/http/examples/client/ClientProxyAuthentication.java

  • my_username替换为您的代理用户名
  • my_password替换为您的代理密码
  • proxy.mycompany.com替换为您的代理主机
  • 8080替换为您的代理端口
  • google.com替换为您要发送HTTP请求的站点的主机名称。
  • /some-path替换为您要将HTTP请求发送到的路径。这使用您之前指定的主机站点(google.com)。

以下示例将对username:password@proxy.mycompany.com:8080进行身份验证,并向http://www.google.com/some-path发送一个GET请求,然后打印响应的HTTP代码。

    CredentialsProvider credsProvider = new BasicCredentialsProvider();
    credsProvider.setCredentials(
            new AuthScope("proxy.mycompany", 8080),
            new UsernamePasswordCredentials("my_username", "my_password"));
    CloseableHttpClient httpclient = HttpClients.custom()
            .setDefaultCredentialsProvider(credsProvider).build();
    try {
        //Replace "google.com" with the target host you want to send the request to
        HttpHost target = new HttpHost("google.com", 80, "http");
        HttpHost proxy = new HttpHost("proxy.mycompany", 8080);

        RequestConfig config = RequestConfig.custom()
            .setProxy(proxy)
            .build();
        CloseableHttpResponse response = null;

        //Replace "/some-path" with the path you want to send a get request to.
        HttpPost httppost = new HttpPost("/some-path");
        httppost.setConfig(config);
        response = httpclient.execute(target, httppost);

        try {
            System.out.println("Return status code is "+response.getStatusLine().getStatusCode());          
        } finally {
            response.close();
        }
    } finally {
        httpclient.close();
    }

1
HttpClient的哪个版本?这是一个重要的元素,因为我之前看到的东西在4.1版本中不起作用,而从4.3和4.5的答案中可以看出事情也发生了变化。 - Daniel C. Sobral
HttpClients自4.3版本开始存在。 - Mismatch

0

对于 HttpClient 4.5 和每个请求的身份验证:

HttpContext httpContext = new BasicHttpContext();
AuthState authState = new AuthState();

authState.update(new BasicScheme(), new UsernamePasswordCredentials("userName", "password"));
httpContext.setAttribute(HttpClientContext.PROXY_AUTH_STATE, authState);
CloseableHttpResponse httpResponse = httpClient.execute(httpRequest, httpContext);

3
如果您没有设置代理主机/端口,那么这个是如何工作的? - Selwyn

0

对于NTLM,我使用了一种更简单的方法:

httpclient.getCredentialsProvider().setCredentials(
                    new AuthScope(proxy_host, proxy_port), 
                    new NTCredentials(this.proxy_user, this.proxy_pass, this.proxy_host, this.proxy_domain));
HttpHost proxy = new HttpHost(this.proxy_host, this.proxy_port, "http");
httpclient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy);

0
如果您必须让您的代码与4.1版本兼容或者想要使用下面的代码片段,那么重要的是要知道httpclient 4.1将不会向代理发送身份验证信息。您可能会得到407 "Proxy Authentication Required"状态码。我已升级到4.3.3,一切正常,尽管在此版本中DefaultHttpClient和ConnRoutePNames已被弃用。希望这可以帮助!
DefaultHttpClient httpclient = new DefaultHttpClient();
httpclient.getCredentialsProvider().setCredentials(
    new AuthScope("PROXY HOST", 8080),
    new UsernamePasswordCredentials("username", "password"));

HttpHost proxy = new HttpHost("PROXY HOST", 8080);

httpclient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接