Redesigned auth caching

git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk@1182515 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Oleg Kalnichevski 2011-10-12 18:33:15 +00:00
parent 4d1b157272
commit 732095943f
13 changed files with 370 additions and 56 deletions

View File

@ -34,6 +34,7 @@ import org.apache.http.Header;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.auth.AuthOption;
import org.apache.http.auth.AuthScheme;
import org.apache.http.auth.MalformedChallengeException;
import org.apache.http.protocol.HttpContext;
@ -52,13 +53,16 @@ public interface AuthenticationStrategy {
/**
* Determines if the given HTTP response response represents
* an authentication challenge that was sent back as a result
* of authentication failure
* of authentication failure.
*
* @param authhost authentication host.
* @param response HTTP response.
* @param context HTTP context.
* @return <code>true</code> if user authentication is required,
* <code>false</code> otherwise.
*/
boolean isAuthenticationRequested(
HttpHost authhost,
HttpResponse response,
HttpContext context);
@ -67,6 +71,7 @@ public interface AuthenticationStrategy {
* challenges, each of which represents an authentication scheme supported
* by the authentication host.
*
* @param authhost authentication host.
* @param response HTTP response.
* @param context HTTP context.
* @return a collection of challenges keyed by names of corresponding
@ -75,6 +80,7 @@ public interface AuthenticationStrategy {
* challenges is not valid or malformed.
*/
Map<String, Header> getChallenges(
HttpHost authhost,
HttpResponse response,
HttpContext context) throws MalformedChallengeException;
@ -82,7 +88,9 @@ public interface AuthenticationStrategy {
* Selects one authentication challenge out of all available and
* creates and generates {@link AuthOption} instance capable of
* processing that challenge.
*
* @param challenges collection of challenges.
* @param authhost authentication host.
* @param response HTTP response.
* @param context HTTP context.
* @return authentication auth schemes that can be used for authentication. Can be empty.
@ -95,4 +103,28 @@ public interface AuthenticationStrategy {
HttpResponse response,
HttpContext context) throws MalformedChallengeException;
/**
* Callback invoked in case of successful authentication.
*
* @param authhost authentication host.
* @param authScheme authentication scheme used.
* @param context HTTP context.
*/
void authSucceeded(
HttpHost authhost,
AuthScheme authScheme,
HttpContext context);
/**
* Callback invoked in case of unsuccessful authentication.
*
* @param authhost authentication host.
* @param authScheme authentication scheme used.
* @param context HTTP context.
*/
void authFailed(
HttpHost authhost,
AuthScheme authScheme,
HttpContext context);
}

View File

@ -127,6 +127,7 @@ public class RequestAuthCache implements HttpRequestInterceptor {
Credentials creds = credsProvider.getCredentials(authScope);
if (creds != null) {
authState.setState(AuthProtocolState.SUCCESS);
authState.update(authScheme, creds);
} else {
this.log.debug("No credentials for preemptive authentication");

View File

@ -39,6 +39,7 @@ import org.apache.http.annotation.Immutable;
import org.apache.http.auth.AuthScheme;
import org.apache.http.auth.AuthState;
import org.apache.http.client.AuthCache;
import org.apache.http.client.AuthenticationStrategy;
import org.apache.http.client.params.AuthPolicy;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
@ -53,8 +54,11 @@ import org.apache.http.protocol.HttpContext;
* additional authentication round-trips.
*
* @since 4.1
*
* @deprecated use {@link AuthenticationStrategy}
*/
@Immutable
@Deprecated
public class ResponseAuthCache implements HttpResponseInterceptor {
private final Log log = LogFactory.getLog(getClass());

View File

@ -44,9 +44,11 @@ import org.apache.http.auth.AuthScope;
import org.apache.http.auth.AuthenticationException;
import org.apache.http.auth.Credentials;
import org.apache.http.auth.MalformedChallengeException;
import org.apache.http.client.AuthCache;
import org.apache.http.client.AuthenticationHandler;
import org.apache.http.client.AuthenticationStrategy;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.params.AuthPolicy;
import org.apache.http.client.protocol.ClientContext;
import org.apache.http.protocol.HttpContext;
@ -68,11 +70,15 @@ class AuthenticationStrategyAdaptor implements AuthenticationStrategy {
this.handler = handler;
}
public boolean isAuthenticationRequested(final HttpResponse response, final HttpContext context) {
public boolean isAuthenticationRequested(
final HttpHost authhost,
final HttpResponse response,
final HttpContext context) {
return this.handler.isAuthenticationRequested(response, context);
}
public Map<String, Header> getChallenges(
final HttpHost authhost,
final HttpResponse response,
final HttpContext context) throws MalformedChallengeException {
return this.handler.getChallenges(response, context);
@ -130,6 +136,44 @@ class AuthenticationStrategyAdaptor implements AuthenticationStrategy {
return options;
}
public void authSucceeded(
final HttpHost authhost, final AuthScheme authScheme, final HttpContext context) {
AuthCache authCache = (AuthCache) context.getAttribute(ClientContext.AUTH_CACHE);
if (isCachable(authScheme)) {
if (authCache == null) {
authCache = new BasicAuthCache();
context.setAttribute(ClientContext.AUTH_CACHE, authCache);
}
if (this.log.isDebugEnabled()) {
this.log.debug("Caching '" + authScheme.getSchemeName() +
"' auth scheme for " + authhost);
}
authCache.put(authhost, authScheme);
}
}
public void authFailed(
final HttpHost authhost, final AuthScheme authScheme, final HttpContext context) {
AuthCache authCache = (AuthCache) context.getAttribute(ClientContext.AUTH_CACHE);
if (authCache == null) {
return;
}
if (this.log.isDebugEnabled()) {
this.log.debug("Removing from cache '" + authScheme.getSchemeName() +
"' auth scheme for " + authhost);
}
authCache.remove(authhost);
}
private boolean isCachable(final AuthScheme authScheme) {
if (authScheme == null || !authScheme.isComplete()) {
return false;
}
String schemeName = authScheme.getSchemeName();
return schemeName.equalsIgnoreCase(AuthPolicy.BASIC) ||
schemeName.equalsIgnoreCase(AuthPolicy.DIGEST);
}
public AuthenticationHandler getHandler() {
return this.handler;
}

View File

@ -49,6 +49,7 @@ import org.apache.http.auth.AuthSchemeRegistry;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.Credentials;
import org.apache.http.auth.MalformedChallengeException;
import org.apache.http.client.AuthCache;
import org.apache.http.client.AuthenticationStrategy;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.params.AuthPolicy;
@ -81,7 +82,10 @@ class AuthenticationStrategyImpl implements AuthenticationStrategy {
this.prefParamName = prefParamName;
}
public boolean isAuthenticationRequested(final HttpResponse response, final HttpContext context) {
public boolean isAuthenticationRequested(
final HttpHost authhost,
final HttpResponse response,
final HttpContext context) {
if (response == null) {
throw new IllegalArgumentException("HTTP response may not be null");
}
@ -90,6 +94,7 @@ class AuthenticationStrategyImpl implements AuthenticationStrategy {
}
public Map<String, Header> getChallenges(
final HttpHost authhost,
final HttpResponse response,
final HttpContext context) throws MalformedChallengeException {
if (response == null) {
@ -200,4 +205,59 @@ class AuthenticationStrategyImpl implements AuthenticationStrategy {
return options;
}
public void authSucceeded(
final HttpHost authhost, final AuthScheme authScheme, final HttpContext context) {
if (authhost == null) {
throw new IllegalArgumentException("Host may not be null");
}
if (authScheme == null) {
throw new IllegalArgumentException("Auth scheme may not be null");
}
if (context == null) {
throw new IllegalArgumentException("HTTP context may not be null");
}
if (isCachable(authScheme)) {
AuthCache authCache = (AuthCache) context.getAttribute(ClientContext.AUTH_CACHE);
if (authCache == null) {
authCache = new BasicAuthCache();
context.setAttribute(ClientContext.AUTH_CACHE, authCache);
}
if (this.log.isDebugEnabled()) {
this.log.debug("Caching '" + authScheme.getSchemeName() +
"' auth scheme for " + authhost);
}
authCache.put(authhost, authScheme);
}
}
protected boolean isCachable(final AuthScheme authScheme) {
if (authScheme == null || !authScheme.isComplete()) {
return false;
}
String schemeName = authScheme.getSchemeName();
return schemeName.equalsIgnoreCase(AuthPolicy.BASIC) ||
schemeName.equalsIgnoreCase(AuthPolicy.DIGEST);
}
public void authFailed(
final HttpHost authhost, final AuthScheme authScheme, final HttpContext context) {
if (authhost == null) {
throw new IllegalArgumentException("Host may not be null");
}
if (authScheme == null) {
throw new IllegalArgumentException("Auth scheme may not be null");
}
if (context == null) {
throw new IllegalArgumentException("HTTP context may not be null");
}
AuthCache authCache = (AuthCache) context.getAttribute(ClientContext.AUTH_CACHE);
if (authCache != null) {
if (this.log.isDebugEnabled()) {
this.log.debug("Removing from cache '" + authScheme.getSchemeName() +
"' auth scheme for " + authhost);
}
authCache.remove(authhost);
}
}
}

View File

@ -36,7 +36,6 @@ import org.apache.http.client.protocol.RequestClientConnControl;
import org.apache.http.client.protocol.RequestDefaultHeaders;
import org.apache.http.client.protocol.RequestProxyAuthentication;
import org.apache.http.client.protocol.RequestTargetAuthentication;
import org.apache.http.client.protocol.ResponseAuthCache;
import org.apache.http.client.protocol.ResponseProcessCookies;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.params.CoreConnectionPNames;
@ -198,7 +197,6 @@ public class DefaultHttpClient extends AbstractHttpClient {
* <li>{@link RequestAddCookies}</li>
* <li>{@link ResponseProcessCookies}</li>
* <li>{@link RequestAuthCache}</li>
* <li>{@link ResponseAuthCache}</li>
* <li>{@link RequestTargetAuthentication}</li>
* <li>{@link RequestProxyAuthentication}</li>
* </ul>
@ -221,7 +219,6 @@ public class DefaultHttpClient extends AbstractHttpClient {
httpproc.addInterceptor(new ResponseProcessCookies());
// HTTP authentication interceptors
httpproc.addInterceptor(new RequestAuthCache());
httpproc.addInterceptor(new ResponseAuthCache());
httpproc.addInterceptor(new RequestTargetAuthentication());
httpproc.addInterceptor(new RequestProxyAuthentication());
return httpproc;

View File

@ -184,9 +184,9 @@ public class DefaultRequestDirector implements RequestDirector {
/** The currently allocated connection. */
protected ManagedClientConnection managedConn;
protected AuthState targetAuthState;
protected final AuthState targetAuthState;
protected AuthState proxyAuthState;
protected final AuthState proxyAuthState;
private final HttpAuthenticator authenticator;
@ -351,6 +351,8 @@ public class DefaultRequestDirector implements RequestDirector {
this.execCount = 0;
this.redirectCount = 0;
this.targetAuthState = new AuthState();
this.proxyAuthState = new AuthState();
this.maxRedirects = this.params.getIntParameter(ClientPNames.MAX_REDIRECTS, 100);
}
@ -400,16 +402,8 @@ public class DefaultRequestDirector implements RequestDirector {
HttpContext context)
throws HttpException, IOException {
targetAuthState = (AuthState) context.getAttribute(ClientContext.TARGET_AUTH_STATE);
if (targetAuthState == null) {
targetAuthState = new AuthState();
context.setAttribute(ClientContext.TARGET_AUTH_STATE, targetAuthState);
}
proxyAuthState = (AuthState) context.getAttribute(ClientContext.PROXY_AUTH_STATE);
if (proxyAuthState == null) {
proxyAuthState = new AuthState();
context.setAttribute(ClientContext.PROXY_AUTH_STATE, proxyAuthState);
}
context.setAttribute(ClientContext.TARGET_AUTH_STATE, targetAuthState);
context.setAttribute(ClientContext.PROXY_AUTH_STATE, proxyAuthState);
HttpRequest orig = request;
RequestWrapper origWrapper = wrapRequest(orig);
@ -910,7 +904,7 @@ public class DefaultRequestDirector implements RequestDirector {
}
if (HttpClientParams.isAuthenticating(this.params)) {
if (this.authenticator.isAuthenticationRequested(response,
if (this.authenticator.isAuthenticationRequested(proxy, response,
this.proxyAuthStrategy, this.proxyAuthState, context)) {
if (this.authenticator.authenticate(proxy, response,
this.proxyAuthStrategy, this.proxyAuthState, context)) {
@ -1107,19 +1101,16 @@ public class DefaultRequestDirector implements RequestDirector {
}
if (HttpClientParams.isAuthenticating(params)) {
if (this.authenticator.isAuthenticationRequested(response,
HttpHost target = (HttpHost) context.getAttribute(ExecutionContext.HTTP_TARGET_HOST);
if (target == null) {
target = route.getTargetHost();
}
if (target.getPort() < 0) {
Scheme scheme = connManager.getSchemeRegistry().getScheme(target);
target = new HttpHost(target.getHostName(), scheme.getDefaultPort(), target.getSchemeName());
}
if (this.authenticator.isAuthenticationRequested(target, response,
this.targetAuthStrategy, this.targetAuthState, context)) {
HttpHost target = (HttpHost)
context.getAttribute(ExecutionContext.HTTP_TARGET_HOST);
if (target == null) {
target = route.getTargetHost();
}
if (target.getPort() < 0) {
Scheme scheme = connManager.getSchemeRegistry().getScheme(target);
target = new HttpHost(
target.getHostName(), scheme.getDefaultPort(), target.getSchemeName());
}
if (this.authenticator.authenticate(target, response,
this.targetAuthStrategy, this.targetAuthState, context)) {
// Re-try the same request via the same route
@ -1129,9 +1120,9 @@ public class DefaultRequestDirector implements RequestDirector {
}
}
if (this.authenticator.isAuthenticationRequested(response,
HttpHost proxy = route.getProxyHost();
if (this.authenticator.isAuthenticationRequested(proxy, response,
this.proxyAuthStrategy, this.proxyAuthState, context)) {
HttpHost proxy = route.getProxyHost();
if (this.authenticator.authenticate(proxy, response,
this.proxyAuthStrategy, this.proxyAuthState, context)) {
// Re-try the same request via the same route

View File

@ -58,17 +58,19 @@ public class HttpAuthenticator {
}
public boolean isAuthenticationRequested(
final HttpHost host,
final HttpResponse response,
final AuthenticationStrategy authStrategy,
final AuthState authState,
final HttpContext context) {
if (authStrategy.isAuthenticationRequested(response, context)) {
if (authStrategy.isAuthenticationRequested(host, response, context)) {
return true;
} else {
switch (authState.getState()) {
case CHALLENGED:
case HANDSHAKE:
authState.setState(AuthProtocolState.SUCCESS);
authStrategy.authSucceeded(host, authState.getAuthScheme(), context);
break;
case SUCCESS:
break;
@ -89,7 +91,7 @@ public class HttpAuthenticator {
if (this.log.isDebugEnabled()) {
this.log.debug(host.toHostString() + " requested authentication");
}
Map<String, Header> challenges = authStrategy.getChallenges(response, context);
Map<String, Header> challenges = authStrategy.getChallenges(host, response, context);
if (challenges.isEmpty()) {
this.log.debug("Response contains no authentication challenges");
return false;
@ -105,6 +107,7 @@ public class HttpAuthenticator {
case CHALLENGED:
if (authScheme == null) {
this.log.debug("Auth scheme is null");
authStrategy.authFailed(host, authState.getAuthScheme(), context);
authState.reset();
authState.setState(AuthProtocolState.FAILURE);
return false;
@ -118,6 +121,7 @@ public class HttpAuthenticator {
authScheme.processChallenge(challenge);
if (authScheme.isComplete()) {
this.log.debug("Authentication failed");
authStrategy.authFailed(host, authState.getAuthScheme(), context);
authState.reset();
authState.setState(AuthProtocolState.FAILURE);
return false;

View File

@ -176,7 +176,7 @@ public class ProxyClient {
}
if (HttpClientParams.isAuthenticating(this.params)) {
if (this.authenticator.isAuthenticationRequested(response,
if (this.authenticator.isAuthenticationRequested(proxy, response,
this.proxyAuthStrategy, this.proxyAuthState, context)) {
if (this.authenticator.authenticate(proxy, response,
this.proxyAuthStrategy, this.proxyAuthState, context)) {

View File

@ -48,6 +48,7 @@ import org.apache.http.protocol.HttpContext;
import org.junit.Before;
import org.junit.Test;
@Deprecated
public class TestResponseAuthCache {
private HttpHost target;

View File

@ -37,10 +37,12 @@ import org.apache.http.HttpStatus;
import org.apache.http.HttpVersion;
import org.apache.http.auth.AUTH;
import org.apache.http.auth.AuthOption;
import org.apache.http.auth.AuthScheme;
import org.apache.http.auth.AuthSchemeRegistry;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.auth.params.AuthPNames;
import org.apache.http.client.AuthCache;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.params.AuthPolicy;
import org.apache.http.client.protocol.ClientContext;
@ -54,6 +56,7 @@ import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HttpContext;
import org.junit.Assert;
import org.junit.Test;
import org.mockito.Mockito;
/**
* Simple tests for {@link AuthenticationStrategyImpl}.
@ -63,37 +66,42 @@ public class TestAuthenticationStrategy {
@Test(expected=IllegalArgumentException.class)
public void testIsAuthenticationRequestedInvalidInput() throws Exception {
TargetAuthenticationStrategy authStrategy = new TargetAuthenticationStrategy();
HttpHost host = new HttpHost("localhost", 80);
HttpContext context = new BasicHttpContext();
authStrategy.isAuthenticationRequested(null, context);
authStrategy.isAuthenticationRequested(host, null, context);
}
@Test
public void testTargetAuthRequested() throws Exception {
TargetAuthenticationStrategy authStrategy = new TargetAuthenticationStrategy();
HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_UNAUTHORIZED, "UNAUTHORIZED");
HttpHost host = new HttpHost("localhost", 80);
HttpContext context = new BasicHttpContext();
Assert.assertTrue(authStrategy.isAuthenticationRequested(response, context));
Assert.assertTrue(authStrategy.isAuthenticationRequested(host, response, context));
}
@Test
public void testProxyAuthRequested() throws Exception {
ProxyAuthenticationStrategy authStrategy = new ProxyAuthenticationStrategy();
HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_PROXY_AUTHENTICATION_REQUIRED, "UNAUTHORIZED");
HttpHost host = new HttpHost("localhost", 80);
HttpContext context = new BasicHttpContext();
Assert.assertTrue(authStrategy.isAuthenticationRequested(response, context));
Assert.assertTrue(authStrategy.isAuthenticationRequested(host, response, context));
}
@Test(expected=IllegalArgumentException.class)
public void testGetChallengesInvalidInput() throws Exception {
TargetAuthenticationStrategy authStrategy = new TargetAuthenticationStrategy();
HttpHost host = new HttpHost("localhost", 80);
HttpContext context = new BasicHttpContext();
authStrategy.getChallenges(null, context);
authStrategy.getChallenges(host, null, context);
}
@Test
public void testGetChallenges() throws Exception {
TargetAuthenticationStrategy authStrategy = new TargetAuthenticationStrategy();
HttpContext context = new BasicHttpContext();
HttpHost host = new HttpHost("localhost", 80);
HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_UNAUTHORIZED, "UNAUTHORIZED");
Header h1 = new BasicHeader(AUTH.WWW_AUTH, " Basic realm=\"test\"");
Header h2 = new BasicHeader(AUTH.WWW_AUTH, "\t\tDigest realm=\"realm1\", nonce=\"1234\"");
@ -102,7 +110,7 @@ public class TestAuthenticationStrategy {
response.addHeader(h2);
response.addHeader(h3);
Map<String, Header> challenges = authStrategy.getChallenges(response, context);
Map<String, Header> challenges = authStrategy.getChallenges(host, response, context);
Assert.assertNotNull(challenges);
Assert.assertEquals(3, challenges.size());
@ -290,4 +298,141 @@ public class TestAuthenticationStrategy {
Assert.assertTrue(option1.getAuthScheme() instanceof BasicScheme);
}
@Test
public void testAuthSucceededInvalidInput() throws Exception {
TargetAuthenticationStrategy authStrategy = new TargetAuthenticationStrategy();
HttpHost authhost = new HttpHost("locahost", 80);
BasicScheme authScheme = new BasicScheme();
HttpContext context = new BasicHttpContext();
try {
authStrategy.authSucceeded(null, authScheme, context);
Assert.fail("IllegalArgumentException expected");
} catch (IllegalArgumentException ex) {
}
try {
authStrategy.authSucceeded(authhost, null, context);
Assert.fail("IllegalArgumentException expected");
} catch (IllegalArgumentException ex) {
}
try {
authStrategy.authSucceeded(authhost, authScheme, null);
Assert.fail("IllegalArgumentException expected");
} catch (IllegalArgumentException ex) {
}
}
@Test
public void testAuthSucceeded() throws Exception {
TargetAuthenticationStrategy authStrategy = new TargetAuthenticationStrategy();
HttpHost authhost = new HttpHost("somehost", 80);
BasicScheme authScheme = new BasicScheme();
authScheme.processChallenge(new BasicHeader(AUTH.WWW_AUTH, "Basic realm=test"));
AuthCache authCache = Mockito.mock(AuthCache.class);
HttpContext context = new BasicHttpContext();
context.setAttribute(ClientContext.AUTH_CACHE, authCache);
authStrategy.authSucceeded(authhost, authScheme, context);
Mockito.verify(authCache).put(authhost, authScheme);
}
@Test
public void testAuthSucceededNoCache() throws Exception {
TargetAuthenticationStrategy authStrategy = new TargetAuthenticationStrategy();
HttpHost authhost = new HttpHost("somehost", 80);
BasicScheme authScheme = new BasicScheme();
authScheme.processChallenge(new BasicHeader(AUTH.WWW_AUTH, "Basic realm=test"));
HttpContext context = new BasicHttpContext();
context.setAttribute(ClientContext.AUTH_CACHE, null);
authStrategy.authSucceeded(authhost, authScheme, context);
AuthCache authCache = (AuthCache) context.getAttribute(ClientContext.AUTH_CACHE);
Assert.assertNotNull(authCache);
}
@Test
public void testAuthScemeNotCompleted() throws Exception {
TargetAuthenticationStrategy authStrategy = new TargetAuthenticationStrategy();
HttpHost authhost = new HttpHost("somehost", 80);
BasicScheme authScheme = new BasicScheme();
AuthCache authCache = Mockito.mock(AuthCache.class);
HttpContext context = new BasicHttpContext();
context.setAttribute(ClientContext.AUTH_CACHE, authCache);
authStrategy.authSucceeded(authhost, authScheme, context);
Mockito.verify(authCache, Mockito.never()).put(authhost, authScheme);
}
@Test
public void testAuthScemeNonCacheable() throws Exception {
TargetAuthenticationStrategy authStrategy = new TargetAuthenticationStrategy();
HttpHost authhost = new HttpHost("somehost", 80);
AuthScheme authScheme = Mockito.mock(AuthScheme.class);
Mockito.when(authScheme.isComplete()).thenReturn(true);
Mockito.when(authScheme.getSchemeName()).thenReturn("whatever");
AuthCache authCache = Mockito.mock(AuthCache.class);
HttpContext context = new BasicHttpContext();
context.setAttribute(ClientContext.AUTH_CACHE, authCache);
authStrategy.authSucceeded(authhost, authScheme, context);
Mockito.verify(authCache, Mockito.never()).put(authhost, authScheme);
}
@Test
public void testAuthFailedInvalidInput() throws Exception {
TargetAuthenticationStrategy authStrategy = new TargetAuthenticationStrategy();
HttpHost authhost = new HttpHost("locahost", 80);
BasicScheme authScheme = new BasicScheme();
HttpContext context = new BasicHttpContext();
try {
authStrategy.authFailed(null, authScheme, context);
Assert.fail("IllegalArgumentException expected");
} catch (IllegalArgumentException ex) {
}
try {
authStrategy.authFailed(authhost, null, context);
Assert.fail("IllegalArgumentException expected");
} catch (IllegalArgumentException ex) {
}
try {
authStrategy.authFailed(authhost, authScheme, null);
Assert.fail("IllegalArgumentException expected");
} catch (IllegalArgumentException ex) {
}
}
@Test
public void testAuthFailed() throws Exception {
TargetAuthenticationStrategy authStrategy = new TargetAuthenticationStrategy();
HttpHost authhost = new HttpHost("somehost", 80);
BasicScheme authScheme = new BasicScheme();
authScheme.processChallenge(new BasicHeader(AUTH.WWW_AUTH, "Basic realm=test"));
AuthCache authCache = Mockito.mock(AuthCache.class);
HttpContext context = new BasicHttpContext();
context.setAttribute(ClientContext.AUTH_CACHE, authCache);
authStrategy.authFailed(authhost, authScheme, context);
Mockito.verify(authCache).remove(authhost);
}
@Test
public void testAuthFailedNoCache() throws Exception {
TargetAuthenticationStrategy authStrategy = new TargetAuthenticationStrategy();
HttpHost authhost = new HttpHost("somehost", 80);
BasicScheme authScheme = new BasicScheme();
HttpContext context = new BasicHttpContext();
context.setAttribute(ClientContext.AUTH_CACHE, null);
authStrategy.authFailed(authhost, authScheme, context);
}
}

View File

@ -345,9 +345,10 @@ public class TestClientAuthentication extends BasicServerTestBase {
@Override
public boolean isAuthenticationRequested(
final HttpHost host,
final HttpResponse response,
final HttpContext context) {
boolean res = super.isAuthenticationRequested(response, context);
boolean res = super.isAuthenticationRequested(host, response, context);
if (res == true) {
synchronized (this) {
this.count++;

View File

@ -36,11 +36,13 @@ import org.apache.http.HttpVersion;
import org.apache.http.auth.AUTH;
import org.apache.http.auth.AuthOption;
import org.apache.http.auth.AuthProtocolState;
import org.apache.http.auth.AuthScheme;
import org.apache.http.auth.AuthSchemeRegistry;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.AuthState;
import org.apache.http.auth.Credentials;
import org.apache.http.auth.MalformedChallengeException;
import org.apache.http.client.AuthCache;
import org.apache.http.client.AuthenticationStrategy;
import org.apache.http.client.protocol.ClientContext;
import org.apache.http.impl.auth.BasicScheme;
@ -51,6 +53,7 @@ import org.apache.http.impl.auth.NTLMSchemeFactory;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicHttpResponse;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.ExecutionContext;
import org.apache.http.protocol.HttpContext;
import org.junit.Assert;
import org.junit.Before;
@ -61,17 +64,27 @@ public class TestHttpAuthenticator {
private AuthenticationStrategy authStrategy;
private AuthState authState;
private AuthScheme authScheme;
private HttpContext context;
private HttpHost host;
private HttpHost proxy;
private Credentials credentials;
private BasicCredentialsProvider credentialsProvider;
private AuthSchemeRegistry authSchemeRegistry;
private AuthCache authCache;
private HttpAuthenticator httpAuthenticator;
@Before
public void setUp() {
public void setUp() throws Exception {
this.authStrategy = Mockito.mock(AuthenticationStrategy.class);
this.authState = new AuthState();
this.authScheme = new BasicScheme();
this.authScheme.processChallenge(new BasicHeader(AUTH.WWW_AUTH, "Basic realm=test"));
this.context = new BasicHttpContext();
this.host = new HttpHost("localhost", 80);
this.proxy = new HttpHost("localhost", 8888);
this.context.setAttribute(ExecutionContext.HTTP_TARGET_HOST, this.host);
this.context.setAttribute(ExecutionContext.HTTP_PROXY_HOST, this.proxy);
this.credentials = Mockito.mock(Credentials.class);
this.credentialsProvider = new BasicCredentialsProvider();
this.credentialsProvider.setCredentials(AuthScope.ANY, this.credentials);
@ -81,6 +94,8 @@ public class TestHttpAuthenticator {
this.authSchemeRegistry.register("digest", new DigestSchemeFactory());
this.authSchemeRegistry.register("ntlm", new NTLMSchemeFactory());
this.context.setAttribute(ClientContext.AUTHSCHEME_REGISTRY, this.authSchemeRegistry);
this.authCache = Mockito.mock(AuthCache.class);
this.context.setAttribute(ClientContext.AUTH_CACHE, this.authCache);
this.httpAuthenticator = new HttpAuthenticator();
}
@ -88,53 +103,65 @@ public class TestHttpAuthenticator {
public void testAuthenticationRequested() throws Exception {
HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_UNAUTHORIZED, "UNAUTHORIZED");
Mockito.when(this.authStrategy.isAuthenticationRequested(
Mockito.any(HttpResponse.class), Mockito.any(HttpContext.class))).thenReturn(Boolean.TRUE);
Mockito.any(HttpHost.class),
Mockito.any(HttpResponse.class),
Mockito.any(HttpContext.class))).thenReturn(Boolean.TRUE);
Assert.assertTrue(this.httpAuthenticator.isAuthenticationRequested(
response, this.authStrategy, this.authState, this.context));
this.host, response, this.authStrategy, this.authState, this.context));
Mockito.verify(this.authStrategy).isAuthenticationRequested(response, this.context);
Mockito.verify(this.authStrategy).isAuthenticationRequested(this.host, response, this.context);
}
@Test
public void testAuthenticationNotRequestedUnchallenged() throws Exception {
HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK");
Mockito.when(this.authStrategy.isAuthenticationRequested(
Mockito.any(HttpResponse.class), Mockito.any(HttpContext.class))).thenReturn(Boolean.FALSE);
Mockito.any(HttpHost.class),
Mockito.any(HttpResponse.class),
Mockito.any(HttpContext.class))).thenReturn(Boolean.FALSE);
Assert.assertFalse(this.httpAuthenticator.isAuthenticationRequested(
response, this.authStrategy, this.authState, this.context));
this.host, response, this.authStrategy, this.authState, this.context));
Assert.assertEquals(AuthProtocolState.UNCHALLENGED, this.authState.getState());
Mockito.verify(this.authStrategy).isAuthenticationRequested(response, this.context);
Mockito.verify(this.authStrategy).isAuthenticationRequested(this.host, response, this.context);
}
@Test
public void testAuthenticationNotRequestedSuccess1() throws Exception {
HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK");
Mockito.when(this.authStrategy.isAuthenticationRequested(
Mockito.any(HttpResponse.class), Mockito.any(HttpContext.class))).thenReturn(Boolean.FALSE);
Mockito.any(HttpHost.class),
Mockito.any(HttpResponse.class),
Mockito.any(HttpContext.class))).thenReturn(Boolean.FALSE);
this.authState.update(this.authScheme, this.credentials);
this.authState.setState(AuthProtocolState.CHALLENGED);
Assert.assertFalse(this.httpAuthenticator.isAuthenticationRequested(
response, this.authStrategy, this.authState, this.context));
this.host, response, this.authStrategy, this.authState, this.context));
Assert.assertEquals(AuthProtocolState.SUCCESS, this.authState.getState());
Mockito.verify(this.authStrategy).isAuthenticationRequested(response, this.context);
Mockito.verify(this.authStrategy).isAuthenticationRequested(this.host, response, this.context);
Mockito.verify(this.authStrategy).authSucceeded(this.host, this.authScheme, this.context);
}
@Test
public void testAuthenticationNotRequestedSuccess2() throws Exception {
HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK");
Mockito.when(this.authStrategy.isAuthenticationRequested(
Mockito.any(HttpResponse.class), Mockito.any(HttpContext.class))).thenReturn(Boolean.FALSE);
Mockito.any(HttpHost.class),
Mockito.any(HttpResponse.class),
Mockito.any(HttpContext.class))).thenReturn(Boolean.FALSE);
this.authState.update(this.authScheme, this.credentials);
this.authState.setState(AuthProtocolState.HANDSHAKE);
Assert.assertFalse(this.httpAuthenticator.isAuthenticationRequested(
response, this.authStrategy, this.authState, this.context));
this.host, response, this.authStrategy, this.authState, this.context));
Assert.assertEquals(AuthProtocolState.SUCCESS, this.authState.getState());
Mockito.verify(this.authStrategy).isAuthenticationRequested(response, this.context);
Mockito.verify(this.authStrategy).isAuthenticationRequested(this.host, response, this.context);
Mockito.verify(this.authStrategy).authSucceeded(this.host, this.authScheme, this.context);
}
@Test
@ -168,6 +195,7 @@ public class TestHttpAuthenticator {
HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_UNAUTHORIZED, "UNAUTHORIZED");
Mockito.when(this.authStrategy.getChallenges(
Mockito.any(HttpHost.class),
Mockito.any(HttpResponse.class),
Mockito.any(HttpContext.class))).thenReturn(new HashMap<String, Header>());
@ -228,6 +256,7 @@ public class TestHttpAuthenticator {
response.addHeader(new BasicHeader(AUTH.WWW_AUTH, "Digest realm=\"realm1\", nonce=\"1234\""));
this.authState.setState(AuthProtocolState.CHALLENGED);
this.authState.update(this.authScheme, this.credentials);
TargetAuthenticationStrategy authStrategy = new TargetAuthenticationStrategy();
@ -235,6 +264,8 @@ public class TestHttpAuthenticator {
response, authStrategy, this.authState, this.context));
Assert.assertEquals(AuthProtocolState.FAILURE, this.authState.getState());
Mockito.verify(this.authCache).remove(host);
}
@Test
@ -271,6 +302,7 @@ public class TestHttpAuthenticator {
Assert.assertTrue(this.httpAuthenticator.authenticate(host,
response, authStrategy, this.authState, this.context));
Assert.assertEquals(AuthProtocolState.HANDSHAKE, this.authState.getState());
}
@ -306,7 +338,9 @@ public class TestHttpAuthenticator {
this.authState.setState(AuthProtocolState.CHALLENGED);
Mockito.doThrow(new MalformedChallengeException()).when(this.authStrategy).getChallenges(
Mockito.any(HttpResponse.class), Mockito.any(HttpContext.class));
Mockito.any(HttpHost.class),
Mockito.any(HttpResponse.class),
Mockito.any(HttpContext.class));
Assert.assertFalse(this.httpAuthenticator.authenticate(host,
response, this.authStrategy, this.authState, this.context));