You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by ol...@apache.org on 2012/10/04 13:03:15 UTC

svn commit: r1393984 - in /httpcomponents/httpclient/branches/4.2.x: ./ httpclient/src/main/java/org/apache/http/client/protocol/ httpclient/src/test/java/org/apache/http/impl/client/

Author: olegk
Date: Thu Oct  4 11:03:15 2012
New Revision: 1393984

URL: http://svn.apache.org/viewvc?rev=1393984&view=rev
Log:
HTTPCLIENT-1241: (regression) Preemptive BASIC authentication failure should be considered final and no further attempts to re-authenticate using the same credentials should be made

Modified:
    httpcomponents/httpclient/branches/4.2.x/RELEASE_NOTES.txt
    httpcomponents/httpclient/branches/4.2.x/httpclient/src/main/java/org/apache/http/client/protocol/RequestAuthCache.java
    httpcomponents/httpclient/branches/4.2.x/httpclient/src/test/java/org/apache/http/impl/client/TestClientAuthentication.java
    httpcomponents/httpclient/branches/4.2.x/httpclient/src/test/java/org/apache/http/impl/client/TestClientReauthentication.java

Modified: httpcomponents/httpclient/branches/4.2.x/RELEASE_NOTES.txt
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/branches/4.2.x/RELEASE_NOTES.txt?rev=1393984&r1=1393983&r2=1393984&view=diff
==============================================================================
--- httpcomponents/httpclient/branches/4.2.x/RELEASE_NOTES.txt (original)
+++ httpcomponents/httpclient/branches/4.2.x/RELEASE_NOTES.txt Thu Oct  4 11:03:15 2012
@@ -1,5 +1,9 @@
 Changes since 4.2.1
 
+* [HTTPCLIENT-1241] (regression) Preemptive BASIC authentication failure should be considered 
+  final and no further attempts to re-authenticate using the same credentials should be made. 
+  Contributed by Oleg Kalnichevski <olegk at apache.org>
+
 * [HTTPCLIENT-1229] Fixed NPE in BasicClientConnectionManager that can be triggered by releasing
   connection after the connection manager has already been shut down. 
   Contributed by Oleg Kalnichevski <olegk at apache.org>

Modified: httpcomponents/httpclient/branches/4.2.x/httpclient/src/main/java/org/apache/http/client/protocol/RequestAuthCache.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/branches/4.2.x/httpclient/src/main/java/org/apache/http/client/protocol/RequestAuthCache.java?rev=1393984&r1=1393983&r2=1393984&view=diff
==============================================================================
--- httpcomponents/httpclient/branches/4.2.x/httpclient/src/main/java/org/apache/http/client/protocol/RequestAuthCache.java (original)
+++ httpcomponents/httpclient/branches/4.2.x/httpclient/src/main/java/org/apache/http/client/protocol/RequestAuthCache.java Thu Oct  4 11:03:15 2012
@@ -127,7 +127,11 @@ public class RequestAuthCache implements
         Credentials creds = credsProvider.getCredentials(authScope);
 
         if (creds != null) {
-            authState.setState(AuthProtocolState.SUCCESS);
+            if ("BASIC".equalsIgnoreCase(authScheme.getSchemeName())) {
+                authState.setState(AuthProtocolState.CHALLENGED);
+            } else {
+                authState.setState(AuthProtocolState.SUCCESS);
+            }
             authState.update(authScheme, creds);
         } else {
             this.log.debug("No credentials for preemptive authentication");

Modified: httpcomponents/httpclient/branches/4.2.x/httpclient/src/test/java/org/apache/http/impl/client/TestClientAuthentication.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/branches/4.2.x/httpclient/src/test/java/org/apache/http/impl/client/TestClientAuthentication.java?rev=1393984&r1=1393983&r2=1393984&view=diff
==============================================================================
--- httpcomponents/httpclient/branches/4.2.x/httpclient/src/test/java/org/apache/http/impl/client/TestClientAuthentication.java (original)
+++ httpcomponents/httpclient/branches/4.2.x/httpclient/src/test/java/org/apache/http/impl/client/TestClientAuthentication.java Thu Oct  4 11:03:15 2012
@@ -27,6 +27,7 @@ package org.apache.http.impl.client;
 
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
+import java.util.concurrent.atomic.AtomicLong;
 
 import org.apache.http.Consts;
 import org.apache.http.HttpEntity;
@@ -38,14 +39,17 @@ import org.apache.http.HttpStatus;
 import org.apache.http.auth.AuthScope;
 import org.apache.http.auth.Credentials;
 import org.apache.http.auth.UsernamePasswordCredentials;
+import org.apache.http.client.AuthCache;
 import org.apache.http.client.ClientProtocolException;
 import org.apache.http.client.CredentialsProvider;
 import org.apache.http.client.NonRepeatableRequestException;
 import org.apache.http.client.methods.HttpGet;
 import org.apache.http.client.methods.HttpPost;
 import org.apache.http.client.methods.HttpPut;
+import org.apache.http.client.protocol.ClientContext;
 import org.apache.http.entity.InputStreamEntity;
 import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.auth.BasicScheme;
 import org.apache.http.localserver.BasicAuthTokenExtractor;
 import org.apache.http.localserver.BasicServerTestBase;
 import org.apache.http.localserver.LocalTestServer;
@@ -336,11 +340,11 @@ public class TestClientAuthentication ex
 
     static class TestTargetAuthenticationStrategy extends TargetAuthenticationStrategy {
 
-        private int count;
+        private AtomicLong count;
 
         public TestTargetAuthenticationStrategy() {
             super();
-            this.count = 0;
+            this.count = new AtomicLong();
         }
 
         @Override
@@ -350,17 +354,13 @@ public class TestClientAuthentication ex
                 final HttpContext context) {
             boolean res = super.isAuthenticationRequested(host, response, context);
             if (res == true) {
-                synchronized (this) {
-                    this.count++;
-                }
+                this.count.incrementAndGet();
             }
             return res;
         }
 
-        public int getCount() {
-            synchronized (this) {
-                return this.count;
-            }
+        public long getCount() {
+            return this.count.get();
         }
 
     }
@@ -381,15 +381,16 @@ public class TestClientAuthentication ex
 
         HttpContext context = new BasicHttpContext();
 
+        HttpHost targethost = getServerHttp();
         HttpGet httpget = new HttpGet("/");
 
-        HttpResponse response1 = this.httpclient.execute(getServerHttp(), httpget, context);
+        HttpResponse response1 = this.httpclient.execute(targethost, httpget, context);
         HttpEntity entity1 = response1.getEntity();
         Assert.assertEquals(HttpStatus.SC_OK, response1.getStatusLine().getStatusCode());
         Assert.assertNotNull(entity1);
         EntityUtils.consume(entity1);
 
-        HttpResponse response2 = this.httpclient.execute(getServerHttp(), httpget, context);
+        HttpResponse response2 = this.httpclient.execute(targethost, httpget, context);
         HttpEntity entity2 = response1.getEntity();
         Assert.assertEquals(HttpStatus.SC_OK, response2.getStatusLine().getStatusCode());
         Assert.assertNotNull(entity2);
@@ -428,4 +429,94 @@ public class TestClientAuthentication ex
         EntityUtils.consume(entity);
     }
 
+    static class CountingAuthHandler implements HttpRequestHandler {
+
+        private AtomicLong count;
+
+        public CountingAuthHandler() {
+            super();
+            this.count = new AtomicLong();
+        }
+
+        public void handle(
+                final HttpRequest request,
+                final HttpResponse response,
+                final HttpContext context) throws HttpException, IOException {
+            this.count.incrementAndGet();
+            String creds = (String) context.getAttribute("creds");
+            if (creds == null || !creds.equals("test:test")) {
+                response.setStatusCode(HttpStatus.SC_UNAUTHORIZED);
+            } else {
+                response.setStatusCode(HttpStatus.SC_OK);
+                StringEntity entity = new StringEntity("success", Consts.ASCII);
+                response.setEntity(entity);
+            }
+        }
+
+        public long getCount() {
+            return this.count.get();
+        }
+
+    }
+
+    @Test
+    public void testPreemptiveAuthentication() throws Exception {
+        CountingAuthHandler requestHandler = new CountingAuthHandler();
+        this.localServer.register("*", requestHandler);
+        this.localServer.start();
+
+        BasicCredentialsProvider credsProvider = new BasicCredentialsProvider();
+        credsProvider.setCredentials(AuthScope.ANY,
+                new UsernamePasswordCredentials("test", "test"));
+
+        this.httpclient.setCredentialsProvider(credsProvider);
+
+        HttpHost targethost = getServerHttp();
+
+        HttpContext context = new BasicHttpContext();
+        AuthCache authCache = new BasicAuthCache();
+        authCache.put(targethost, new BasicScheme());
+        context.setAttribute(ClientContext.AUTH_CACHE, authCache);
+
+        HttpGet httpget = new HttpGet("/");
+
+        HttpResponse response1 = this.httpclient.execute(targethost, httpget, context);
+        HttpEntity entity1 = response1.getEntity();
+        Assert.assertEquals(HttpStatus.SC_OK, response1.getStatusLine().getStatusCode());
+        Assert.assertNotNull(entity1);
+        EntityUtils.consume(entity1);
+
+        Assert.assertEquals(1, requestHandler.getCount());
+    }
+
+    @Test
+    public void testPreemptiveAuthenticationFailure() throws Exception {
+        CountingAuthHandler requestHandler = new CountingAuthHandler();
+        this.localServer.register("*", requestHandler);
+        this.localServer.start();
+
+        BasicCredentialsProvider credsProvider = new BasicCredentialsProvider();
+        credsProvider.setCredentials(AuthScope.ANY,
+                new UsernamePasswordCredentials("test", "stuff"));
+
+        this.httpclient.setCredentialsProvider(credsProvider);
+
+        HttpHost targethost = getServerHttp();
+
+        HttpContext context = new BasicHttpContext();
+        AuthCache authCache = new BasicAuthCache();
+        authCache.put(targethost, new BasicScheme());
+        context.setAttribute(ClientContext.AUTH_CACHE, authCache);
+
+        HttpGet httpget = new HttpGet("/");
+
+        HttpResponse response1 = this.httpclient.execute(targethost, httpget, context);
+        HttpEntity entity1 = response1.getEntity();
+        Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, response1.getStatusLine().getStatusCode());
+        Assert.assertNotNull(entity1);
+        EntityUtils.consume(entity1);
+
+        Assert.assertEquals(1, requestHandler.getCount());
+    }
+
 }

Modified: httpcomponents/httpclient/branches/4.2.x/httpclient/src/test/java/org/apache/http/impl/client/TestClientReauthentication.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/branches/4.2.x/httpclient/src/test/java/org/apache/http/impl/client/TestClientReauthentication.java?rev=1393984&r1=1393983&r2=1393984&view=diff
==============================================================================
--- httpcomponents/httpclient/branches/4.2.x/httpclient/src/test/java/org/apache/http/impl/client/TestClientReauthentication.java (original)
+++ httpcomponents/httpclient/branches/4.2.x/httpclient/src/test/java/org/apache/http/impl/client/TestClientReauthentication.java Thu Oct  4 11:03:15 2012
@@ -26,6 +26,7 @@
 package org.apache.http.impl.client;
 
 import java.io.IOException;
+import java.util.Collections;
 import java.util.concurrent.atomic.AtomicLong;
 
 import org.apache.http.Consts;
@@ -36,15 +37,20 @@ import org.apache.http.HttpResponse;
 import org.apache.http.HttpResponseInterceptor;
 import org.apache.http.HttpStatus;
 import org.apache.http.auth.AUTH;
+import org.apache.http.auth.AuthScheme;
 import org.apache.http.auth.AuthScope;
 import org.apache.http.auth.Credentials;
 import org.apache.http.auth.UsernamePasswordCredentials;
+import org.apache.http.auth.params.AuthPNames;
 import org.apache.http.client.CredentialsProvider;
 import org.apache.http.client.methods.HttpGet;
 import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.auth.BasicScheme;
+import org.apache.http.impl.auth.BasicSchemeFactory;
 import org.apache.http.localserver.BasicServerTestBase;
 import org.apache.http.localserver.LocalTestServer;
 import org.apache.http.localserver.RequestBasicAuth;
+import org.apache.http.params.HttpParams;
 import org.apache.http.protocol.BasicHttpContext;
 import org.apache.http.protocol.BasicHttpProcessor;
 import org.apache.http.protocol.HttpContext;
@@ -66,7 +72,7 @@ public class TestClientReauthentication 
                 final HttpResponse response,
                 final HttpContext context) throws HttpException, IOException {
             if (response.getStatusLine().getStatusCode() == HttpStatus.SC_UNAUTHORIZED) {
-                response.addHeader(AUTH.WWW_AUTH, "Basic realm=\"test realm\"");
+                response.addHeader(AUTH.WWW_AUTH, "MyBasic realm=\"test realm\"");
             }
         }
 
@@ -143,11 +149,37 @@ public class TestClientReauthentication 
         this.localServer.register("*", new AuthHandler());
         this.localServer.start();
 
+        this.httpclient.getAuthSchemes().register("MyBasic", new BasicSchemeFactory() {
+
+            @Override
+            public AuthScheme newInstance(HttpParams params) {
+                return new BasicScheme() {
+
+                    @Override
+                    public String getSchemeName() {
+                        return "MyBasic";
+                    }
+
+                };
+            }
+
+        });
+        this.httpclient.setTargetAuthenticationStrategy(new TargetAuthenticationStrategy() {
+
+            @Override
+            protected boolean isCachable(final AuthScheme authScheme) {
+                return "MyBasic".equalsIgnoreCase(authScheme.getSchemeName());
+            }
+
+        });
         TestCredentialsProvider credsProvider = new TestCredentialsProvider(
                 new UsernamePasswordCredentials("test", "test"));
 
         this.httpclient.setCredentialsProvider(credsProvider);
 
+        this.httpclient.getParams().setParameter(AuthPNames.TARGET_AUTH_PREF,
+                Collections.singletonList("MyBasic"));
+
         HttpContext context = new BasicHttpContext();
         for (int i = 0; i < 10; i++) {
             HttpGet httpget = new HttpGet("/");