使用Apache HTTP Components进行HTTP身份验证:强制发送挑战

5

我需要与一个需要身份验证的不太常见的Web服务器进行通信。如果我不提供凭据,将显示登录表单。但是,如果我提供未经请求的基本身份验证凭据,则可以直接访问所需内容。

wget 直接支持此功能:

# this fails and downloads a form:
wget https://weird.egg/data.txt --http-user=me --http-password=shhh

# this works and downloads the document:
wget https://weird.egg/data.txt --http-user=me --http-password=shhh --auth-no-challenge

现在我的问题是:如何使用Apache的HTTP组件在Java中进行下载?
这是我已经得到的代码(还有一个代理,并且我在wget中使用“-Y on”,并且我有一个匹配的https_proxy环境变量)。
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.conn.params.ConnRoutePNames;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import java.net.URI;

// ...

DefaultHttpClient hc = new DefaultHttpClient();
hc.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, new HttpHost(proxy_name, proxy_port));

URI uri = new URI("https://weird.egg/data.txt");

hc..getCredentialsProvider().setCredentials(new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT, AuthScope.ANY_REALM, AuthScope.ANY_SCHEME), new UsernamePasswordCredentials("me", "shh"));

hc.execute(new HttpGet(uri)); // etc

然而,我只能得到登录表单页面,而不是实际的文档。我怀疑DefaultHttpClient没有像wget那样主动发送凭据。有没有办法让Java程序发送凭据?

1个回答

10

没关系。我通过不尝试使用任何库身份验证方法,而是将基本身份验证标头强制添加到请求中来解决了这个问题:

HttpGet get = new HttpGet(uri);

String basic_auth = new String(Base64.encodeBase64((username + ":" + password).getBytes()));
get.addHeader("Authorization", "Basic " + basic_auth);

hc.execute(get); // etc

(这需要额外的 import org.apache.commons.codec.binary.Base64;,但反过来我们可以删除与凭据相关的导入。)


太好了,谢谢。框架解决方案对我也没有起作用。手动添加标头有效。 - Bogdan Zurac
谢谢。我在使用Maven HTTP Wagon客户端时遇到了同样的问题,并通过手动添加Header解决了它。 - Andreas Panagiotidis
1
现在你可以直接使用java.util.Base64.getEncoder().encodeToString(something),无需依赖于import org.apache.commons.codec.binary.Base64; - eis

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