我使用基本身份验证HttpsUrlConnection
使用Authenticator
并设置默认Authenticator
对象,如下所示:
Authenticator.setDefault(new Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("user", "userpass"
.toCharArray());
}
});
当我访问我的Web服务时,连接会调用我的getPasswordAuthentication()
方法来获取凭据并将其发送到Web服务器。只要密码正确,这就可以正常工作。 :)
但是,有人在Web服务器上更改了基本身份验证密码,然后我的请求没有返回。
我调试了它,发生的事情是我对getInputStream()
的调用永远不会返回。 HttpsUrlConnection
确实获得了401响应,并通过再次获取相同的凭据在内部做出反应。但由于我只提供了一个用户和密码,这将再次失败(并再次......)。
所以我的问题是:如何防止这种情况以及哪里有一个钩子来对错误的密码做出反应(分别为401响应),这样我就可以显示相应的错误消息并取消请求?
以下是HttpsUrlConnection
上重复调用的方法的堆栈跟踪的摘录:
1: MyOwnHttpConnection$3.getPasswordAuthentication() line: 99
2: Authenticator.requestPasswordAuthentication(InetAddress, int, String, String, String) line: 162
3: HttpsURLConnectionImpl$HttpsEngine(HttpURLConnectionImpl).getAuthorizationCredentials(String) line: 1205
4: HttpsURLConnectionImpl$HttpsEngine(HttpURLConnectionImpl).processAuthHeader(String, String) line: 1178
5: HttpsURLConnectionImpl$HttpsEngine(HttpURLConnectionImpl).processResponseHeaders() line: 1118
6: HttpsURLConnectionImpl$HttpsEngine(HttpURLConnectionImpl).retrieveResponse() line: 1044
7: HttpsURLConnectionImpl$HttpsEngine(HttpURLConnectionImpl).getInputStream() line: 523
8: HttpsURLConnectionImpl.getInputStream() line: 283
答案 0 :(得分:5)
我通过将请求/响应逻辑抽象为MyRequest
类来解决这个问题。这允许我有一个请求范围的变量,它可以告诉我的Authenticator
是否应该使用指定的用户名和密码发出请求,或者它是否应该停止重试(通过返回null
)。它看起来有点像以下(考虑这个伪代码)
public class MyRequest
{
private boolean alreadyTriedAuthenticating = false;
private URL url;
...
public void send()
{
HttpUrlConnection connection = (HttpUrlConnection) url.openConnection();
Authenticator.setDefault(new Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
if (!alreadyTriedAuthenticating)
{
alreadyTriedAuthenticating = true;
return new PasswordAuthentication(username, password.toCharArray());
}
else
{
return null;
}
}
InputStream in = new BufferedInputStream(connection.getInputStream());
...
}
}
答案 1 :(得分:3)
我希望我知道这个问题的正确答案,因为我遇到了同样的问题。我找不到处理身份验证错误的方法,甚至无法获得有关它的通知。
我最终不得不使用HttpClient
。
HttpClient client = new DefaultHttpClient();
HttpGet get = new HttpGet(loginUrl);
String authString = (userName+":"+password);
get.addHeader("Authorization", "Basic " +
Base64.encodeToString(authString.getBytes(),Base64.NO_WRAP));
HttpResponse response = client.execute(get);
BufferedReader r = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));