Improved auth state tracking in HttpHttpAuthenticator

git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk@1180056 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Oleg Kalnichevski 2011-10-07 14:35:40 +00:00
parent 427d2c24e0
commit 430c3d530e
4 changed files with 83 additions and 20 deletions

View File

@ -67,6 +67,7 @@ public class AuthState {
*/
public void invalidate() {
this.state = AuthProtocolState.UNCHALLENGED;
this.authOptions = null;
this.authScheme = null;
this.authScope = null;
this.credentials = null;
@ -159,15 +160,32 @@ public class AuthState {
* Returns available authentication options.
*
* @return authentication options, if available, <code>null</null> otherwise.
*
* @since 4.2
*/
public Queue<AuthOption> getAuthOptions() {
return this.authOptions;
}
/**
* Returns <code>true</code> if authentication options are available, <code>false</code>
* otherwise.
*
* @return <code>true</code> if authentication options are available, <code>false</code>
* otherwise.
*
* @since 4.2
*/
public boolean hasAuthOptions() {
return this.authOptions != null && !this.authOptions.isEmpty();
}
/**
* Sets authentication options to select from when authenticating.
*
* @param authOptions authentication options
*
* @since 4.2
*/
public void setAuthOptions(final Queue<AuthOption> authOptions) {
this.authOptions = authOptions != null && !authOptions.isEmpty() ? authOptions : null;

View File

@ -63,7 +63,6 @@ public class HttpAuthenticator {
final AuthState authState,
final HttpContext context) {
if (authStrategy.isAuthenticationRequested(response, context)) {
authState.setState(AuthProtocolState.CHALLENGED);
return true;
} else {
switch (authState.getState()) {
@ -93,25 +92,39 @@ public class HttpAuthenticator {
this.log.debug("Response contains no authentication challenges");
return false;
}
AuthScheme authScheme = authState.getAuthScheme();
if (authScheme != null) {
String id = authScheme.getSchemeName();
Header challenge = challenges.get(id.toLowerCase(Locale.US));
if (challenge != null) {
this.log.debug("Authorization challenge processed");
authScheme.processChallenge(challenge);
if (authScheme.isComplete()) {
this.log.debug("Authentication failed");
authState.setState(AuthProtocolState.FAILURE);
authState.setCredentials(null);
return false;
} else {
authState.setState(AuthProtocolState.HANDSHAKE);
return true;
}
} else {
switch (authState.getState()) {
case FAILURE:
return false;
case SUCCESS:
case CHALLENGED:
if (authScheme == null) {
this.log.debug("Auth scheme is null");
authState.invalidate();
// Retry authentication with a different scheme
authState.setState(AuthProtocolState.FAILURE);
return false;
}
case UNCHALLENGED:
if (authScheme != null) {
String id = authScheme.getSchemeName();
Header challenge = challenges.get(id.toLowerCase(Locale.US));
if (challenge != null) {
this.log.debug("Authorization challenge processed");
authScheme.processChallenge(challenge);
if (authScheme.isComplete()) {
this.log.debug("Authentication failed");
authState.invalidate();
authState.setState(AuthProtocolState.FAILURE);
return false;
} else {
authState.setState(AuthProtocolState.HANDSHAKE);
return true;
}
} else {
authState.invalidate();
// Retry authentication with a different scheme
}
}
}
Queue<AuthOption> authOptions = authStrategy.select(challenges, host, response, context);

View File

@ -27,7 +27,6 @@
package org.apache.http.impl.client;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import junit.framework.Assert;

View File

@ -92,7 +92,6 @@ public class TestHttpAuthenticator {
Assert.assertTrue(this.httpAuthenticator.isAuthenticationRequested(
response, this.authStrategy, this.authState, this.context));
Assert.assertEquals(AuthProtocolState.CHALLENGED, this.authState.getState());
Mockito.verify(this.authStrategy).isAuthenticationRequested(response, this.context);
}
@ -204,6 +203,40 @@ public class TestHttpAuthenticator {
response, authStrategy, this.authState, this.context));
}
@Test
public void testAuthenticationFailed() throws Exception {
HttpHost host = new HttpHost("somehost", 80);
HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_UNAUTHORIZED, "UNAUTHORIZED");
response.addHeader(new BasicHeader(AUTH.WWW_AUTH, "Basic realm=\"test\""));
response.addHeader(new BasicHeader(AUTH.WWW_AUTH, "Digest realm=\"realm1\", nonce=\"1234\""));
this.authState.setState(AuthProtocolState.FAILURE);
TargetAuthenticationStrategy authStrategy = new TargetAuthenticationStrategy();
Assert.assertFalse(this.httpAuthenticator.authenticate(host,
response, authStrategy, this.authState, this.context));
Assert.assertEquals(AuthProtocolState.FAILURE, this.authState.getState());
}
@Test
public void testAuthenticationNoAuthScheme() throws Exception {
HttpHost host = new HttpHost("somehost", 80);
HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_UNAUTHORIZED, "UNAUTHORIZED");
response.addHeader(new BasicHeader(AUTH.WWW_AUTH, "Basic realm=\"test\""));
response.addHeader(new BasicHeader(AUTH.WWW_AUTH, "Digest realm=\"realm1\", nonce=\"1234\""));
this.authState.setState(AuthProtocolState.CHALLENGED);
TargetAuthenticationStrategy authStrategy = new TargetAuthenticationStrategy();
Assert.assertFalse(this.httpAuthenticator.authenticate(host,
response, authStrategy, this.authState, this.context));
Assert.assertEquals(AuthProtocolState.FAILURE, this.authState.getState());
}
@Test
public void testAuthenticationFailure() throws Exception {
HttpHost host = new HttpHost("somehost", 80);