Hello,
I have been using httpclient for a while. However, just recently I have run
into two customers that have some kind of issues. To simplify the situation,
I've written a very simple method to test it out. Here is the first issue:
if the username/password are not correct, or if the user does not have
authorization to access that url on the IIS 6.0 site, it enters into an
infinite loop. I am using version 3.0.1.
I've traced the source code. It seems that the problem is in
HttpMethodDirector:
for (int redirectCount = 0;;) { //big loop
authenticate(method); //send out authentication request
executeWithRetry(method); //send out message body
...
boolean retry = false;
...
if (isAuthenticationNeeded(method)) { // NTLM returns 401
in handshake process, or when not authorized
if (processAuthenticationResponse(method)) {
LOG.debug("Retry authentication");
retry = true; //now retry becomes true
}
}
if (!retry) { //it wouldn't break
break;
}
...
The problem (I think) is that even in the NTLM normal handshake process, 401
code is returned, so isAuthenticationNeeded() returns true. This is fine
because when it finishes the handshake process, isAuthenticationNeeded()
returns false. However, if the user name /password are wrong, or the user
doesn't have access to the web resource, 401 code will also be returned.
Since this code uses a loop instead of following/verifying the NTLM
handshake process, it just keeps retrying until connection times out.
Not sure whether this explaination is correct. I would assume that NTLM is
so widely used that there shouldn't be a problem like this. Am I missing
something? Here is how I called httpclient code:
NTCredentials creds = new NTCredentials(context.getUserName(),
context.getPassword(),
context.getServer(), context.getDomain());
HttpState httpState = new HttpState();
httpState.setAuthenticationPreemptive(true);
HttpClient client = new HttpClient();
httpState.setCredentials(new AuthScope(context.getHost(),
context.getPort(),
AuthScope.ANY_REALM, AuthScope.ANY_SCHEME), creds);
GetMethod get = new GetMethod(context.getSitePath());
get.setDoAuthentication(true);
setCredentialsProvider(client, creds);
client.getParams().setAuthenticationPreemptive(true);
client.setState(httpState);
// execute method and handle any error responses.
client.executeMethod(get);
Thanks!
Jeff