You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2012/11/29 15:21:45 UTC

svn commit: r1415177 - /tomcat/trunk/test/org/apache/catalina/authenticator/TestNonLoginAndBasicAuthenticator.java

Author: markt
Date: Thu Nov 29 14:21:45 2012
New Revision: 1415177

URL: http://svn.apache.org/viewvc?rev=1415177&view=rev
Log:
Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=54190
Improve unit tests.
Patch by Brian Burch.

Modified:
    tomcat/trunk/test/org/apache/catalina/authenticator/TestNonLoginAndBasicAuthenticator.java

Modified: tomcat/trunk/test/org/apache/catalina/authenticator/TestNonLoginAndBasicAuthenticator.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/catalina/authenticator/TestNonLoginAndBasicAuthenticator.java?rev=1415177&r1=1415176&r2=1415177&view=diff
==============================================================================
--- tomcat/trunk/test/org/apache/catalina/authenticator/TestNonLoginAndBasicAuthenticator.java (original)
+++ tomcat/trunk/test/org/apache/catalina/authenticator/TestNonLoginAndBasicAuthenticator.java Thu Nov 29 14:21:45 2012
@@ -21,6 +21,8 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+import javax.servlet.http.HttpServletResponse;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
@@ -48,9 +50,13 @@ import org.apache.tomcat.util.buf.ByteCh
  */
 public class TestNonLoginAndBasicAuthenticator extends TomcatBaseTest {
 
+    protected static final Boolean USE_COOKIES = true;
+    protected static final Boolean NO_COOKIES = !USE_COOKIES;
+
     private static final String USER = "user";
     private static final String PWD = "pwd";
     private static final String ROLE = "role";
+    private static final String NICE_METHOD = "Basic";
 
     private static final String HTTP_PREFIX = "http://localhost:";
     private static final String CONTEXT_PATH_NOLOGIN = "/nologin";
@@ -58,12 +64,39 @@ public class TestNonLoginAndBasicAuthent
     private static final String URI_PROTECTED = "/protected";
     private static final String URI_PUBLIC = "/anyoneCanAccess";
 
-    private static final int SHORT_TIMEOUT_SECS = 4;
-    private static final int LONG_TIMEOUT_SECS = 10;
-    private static final long LONG_TIMEOUT_DELAY_MSECS =
-                                    ((LONG_TIMEOUT_SECS + 2) * 1000);
-
-    private static String CLIENT_AUTH_HEADER = "authorization";
+    private static final int SHORT_TIMEOUT_MINS = 1;
+    private static final int LONG_TIMEOUT_MINS = 2;
+    private static final int MANAGER_SCAN_DELAY_SECS = 60;
+    private static final int EXTRA_DELAY_SECS = 5;
+    private static final long TIMEOUT_DELAY_MSECS =
+            (((SHORT_TIMEOUT_MINS * 60)
+                    + MANAGER_SCAN_DELAY_SECS + EXTRA_DELAY_SECS) * 1000);
+
+    private static final String CLIENT_AUTH_HEADER = "authorization";
+    private static final String SERVER_AUTH_HEADER = "WWW-Authenticate";
+    private static final String SERVER_COOKIE_HEADER = "Set-Cookie";
+    private static final String CLIENT_COOKIE_HEADER = "Cookie";
+
+    private static final BasicCredentials NO_CREDENTIALS = null;
+    private static final BasicCredentials GOOD_CREDENTIALS =
+                new BasicCredentials(NICE_METHOD, USER, PWD);
+    private static final BasicCredentials STRANGE_CREDENTIALS =
+                new BasicCredentials("bAsIc", USER, PWD);
+    private static final BasicCredentials BAD_CREDENTIALS =
+                new BasicCredentials(NICE_METHOD, USER, "wrong");
+    private static final BasicCredentials BAD_METHOD =
+                new BasicCredentials("BadMethod", USER, PWD);
+    private static final BasicCredentials SPACED_BASE64 =
+                new BasicCredentials(NICE_METHOD + " ", USER, PWD);
+    private static final BasicCredentials SPACED_USERNAME =
+                new BasicCredentials(NICE_METHOD, " " + USER + " ", PWD);
+    private static final BasicCredentials SPACED_PASSWORD =
+                new BasicCredentials(NICE_METHOD, USER, " " + PWD + " ");
+
+    private Tomcat tomcat;
+    private AuthenticatorBase basicAuthenticator;
+    private AuthenticatorBase nonloginAuthenticator;
+    private List<String> cookies;
 
     /*
      * Try to access an unprotected resource in a webapp that
@@ -72,7 +105,8 @@ public class TestNonLoginAndBasicAuthent
      */
     @Test
     public void testAcceptPublicNonLogin() throws Exception {
-        doTestNonLogin(CONTEXT_PATH_NOLOGIN + URI_PUBLIC, false, 200);
+        doTestNonLogin(CONTEXT_PATH_NOLOGIN + URI_PUBLIC,
+                NO_COOKIES, HttpServletResponse.SC_OK);
     }
 
     /*
@@ -82,7 +116,8 @@ public class TestNonLoginAndBasicAuthent
      */
     @Test
     public void testRejectProtectedNonLogin() throws Exception {
-        doTestNonLogin(CONTEXT_PATH_NOLOGIN + URI_PROTECTED, true, 403);
+        doTestNonLogin(CONTEXT_PATH_NOLOGIN + URI_PROTECTED,
+                NO_COOKIES, HttpServletResponse.SC_FORBIDDEN);
     }
 
     /*
@@ -93,164 +128,378 @@ public class TestNonLoginAndBasicAuthent
     @Test
     public void testAcceptPublicBasic() throws Exception {
         doTestBasic(USER, PWD, CONTEXT_PATH_LOGIN + URI_PUBLIC,
-                false, false, 200, false, 200);
+                NO_CREDENTIALS, NO_COOKIES, HttpServletResponse.SC_OK);
     }
 
     /*
      * Try to access a protected resource in a webapp that
      * has a BASIC login method defined. The access will be
-     * challenged, authenticated and then permitted.
+     * challenged with 401 SC_UNAUTHORIZED, and then be permitted
+     * once authenticated.
      */
     @Test
     public void testAcceptProtectedBasic() throws Exception {
         doTestBasic(USER, PWD, CONTEXT_PATH_LOGIN + URI_PROTECTED,
-                false, true, 401, false, 200);
+                NO_CREDENTIALS, NO_COOKIES, HttpServletResponse.SC_UNAUTHORIZED);
+        doTestBasic(USER, PWD, CONTEXT_PATH_LOGIN + URI_PROTECTED,
+                GOOD_CREDENTIALS, NO_COOKIES, HttpServletResponse.SC_OK);
     }
 
     /*
-     * Try to access a protected resource in a webapp that
-     * has a BASIC login method defined. Verify the server is
-     * prepared to accept non-standard case for the auth scheme.
-     * The access should be challenged, authenticated and then permitted.
+     * This is the same as testAcceptProtectedBasic (above), except
+     * using an invalid password.
+     */
+    @Test
+    public void testAuthMethodBadCredentials() throws Exception {
+        doTestBasic(USER, PWD, CONTEXT_PATH_LOGIN + URI_PROTECTED,
+                NO_CREDENTIALS, NO_COOKIES, HttpServletResponse.SC_UNAUTHORIZED);
+        doTestBasic(USER, PWD, CONTEXT_PATH_LOGIN + URI_PROTECTED,
+                BAD_CREDENTIALS, NO_COOKIES, HttpServletResponse.SC_UNAUTHORIZED);
+    }
+
+    /*
+     * This is the same as testAcceptProtectedBasic (above), except
+     * to verify the server follows RFC2617 by treating the auth-scheme
+     * token as case-insensitive.
      */
     @Test
     public void testAuthMethodCaseBasic() throws Exception {
         doTestBasic(USER, PWD, CONTEXT_PATH_LOGIN + URI_PROTECTED,
-                true, true, 401, false, 200);
+                NO_CREDENTIALS, NO_COOKIES, HttpServletResponse.SC_UNAUTHORIZED);
+        doTestBasic(USER, PWD, CONTEXT_PATH_LOGIN + URI_PROTECTED,
+                STRANGE_CREDENTIALS, NO_COOKIES, HttpServletResponse.SC_OK);
     }
 
     /*
-     * Logon to access a protected resource in a webapp that uses
-     * BASIC authentication. Wait until that session times-out,
-     * then re-access the resource.
-     * This should be rejected with SC_FORBIDDEN 401 status, which
-     * can be followed by successful re-authentication.
+     * This is the same as testAcceptProtectedBasic (above), except
+     * using an invalid authentication method.
+     *
+     * Note: the container ensures the Basic login method is called.
+     *       BasicAuthenticator does not find the expected authentication
+     *       header method, and so does not extract any credentials.
+     *
+     * The request is rejected with 401 SC_UNAUTHORIZED status. RFC2616
+     * says the response body should identify the auth-schemes that are
+     * acceptable for the container.
+     */
+    @Test
+    public void testAuthMethodBadMethod() throws Exception {
+        doTestBasic(USER, PWD, CONTEXT_PATH_LOGIN + URI_PROTECTED,
+                NO_CREDENTIALS, NO_COOKIES, HttpServletResponse.SC_UNAUTHORIZED);
+        doTestBasic(USER, PWD, CONTEXT_PATH_LOGIN + URI_PROTECTED,
+                BAD_METHOD, NO_COOKIES, HttpServletResponse.SC_UNAUTHORIZED);
+    }
+
+    /*
+     * This is the same as testAcceptProtectedBasic (above), except
+     * using excess white space after the authentication method.
+     *
+     * The request is rejected with 401 SC_UNAUTHORIZED status.
+     *
+     * TODO: RFC2617 does not define the separation syntax between the
+     *       auth-scheme and basic-credentials tokens. Tomcat should tolerate
+     *       any reasonable amount of white space and return SC_OK.
+     */
+    @Test
+    public void testAuthMethodExtraSpace() throws Exception {
+        doTestBasic(USER, PWD, CONTEXT_PATH_LOGIN + URI_PROTECTED,
+                NO_CREDENTIALS, NO_COOKIES, HttpServletResponse.SC_UNAUTHORIZED);
+        doTestBasic(USER, PWD, CONTEXT_PATH_LOGIN + URI_PROTECTED,
+                SPACED_BASE64, NO_COOKIES, HttpServletResponse.SC_UNAUTHORIZED);
+    }
+
+    /*
+     * This is the same as testAcceptProtectedBasic (above), except
+     * using white space around the username credential.
+     *
+     * The request is rejected with 401 SC_UNAUTHORIZED status.
+     *
+     * TODO: RFC2617 does not define the separation syntax between the
+     *       auth-scheme and basic-credentials tokens. Tomcat should tolerate
+     *       any reasonable amount of white space and return SC_OK.
+     */
+    @Test
+    public void testUserExtraSpace() throws Exception {
+        doTestBasic(USER, PWD, CONTEXT_PATH_LOGIN + URI_PROTECTED,
+                NO_CREDENTIALS, NO_COOKIES, HttpServletResponse.SC_UNAUTHORIZED);
+        doTestBasic(USER, PWD, CONTEXT_PATH_LOGIN + URI_PROTECTED,
+                SPACED_USERNAME, NO_COOKIES, HttpServletResponse.SC_UNAUTHORIZED);
+    }
+
+    /*
+     * This is the same as testAcceptProtectedBasic (above), except
+     * using white space around the password credential.
+     *
+     * The request is rejected with 401 SC_UNAUTHORIZED status.
+     *
+     * TODO: RFC2617 does not define the separation syntax between the
+     *       auth-scheme and basic-credentials tokens. Tomcat should tolerate
+     *       any reasonable amount of white space and return SC_OK.
      */
     @Test
+    public void testPasswordExtraSpace() throws Exception {
+        doTestBasic(USER, PWD, CONTEXT_PATH_LOGIN + URI_PROTECTED,
+                NO_CREDENTIALS, NO_COOKIES, HttpServletResponse.SC_UNAUTHORIZED);
+        doTestBasic(USER, PWD, CONTEXT_PATH_LOGIN + URI_PROTECTED,
+                SPACED_PASSWORD, NO_COOKIES, HttpServletResponse.SC_UNAUTHORIZED);
+    }
+
+    /*
+     * The default behaviour of BASIC authentication does NOT create
+     * a session on the server. Verify that the client is required to
+     * send a valid authenticate header with every request to access
+     * protected resources.
+     */
+    @Test
+    public void testBasicLoginWithoutSession() throws Exception {
+
+        // this section is identical to testAuthMethodCaseBasic
+        doTestBasic(USER, PWD, CONTEXT_PATH_LOGIN + URI_PROTECTED,
+                NO_CREDENTIALS, NO_COOKIES, HttpServletResponse.SC_UNAUTHORIZED);
+        doTestBasic(USER, PWD, CONTEXT_PATH_LOGIN + URI_PROTECTED,
+                GOOD_CREDENTIALS, NO_COOKIES, HttpServletResponse.SC_OK);
+
+        // next, try to access the protected resource while not providing
+        // credentials. This confirms the server has not retained any state
+        // data which might allow it to authenticate the client. Expect
+        // to be challenged with 401 SC_UNAUTHORIZED.
+        doTestBasic(USER, PWD, CONTEXT_PATH_LOGIN + URI_PROTECTED,
+                NO_CREDENTIALS, NO_COOKIES, HttpServletResponse.SC_UNAUTHORIZED);
+
+        // finally, provide credentials to confirm the resource
+        // can still be accessed with an authentication header.
+        doTestBasic(USER, PWD, CONTEXT_PATH_LOGIN + URI_PROTECTED,
+                GOOD_CREDENTIALS, NO_COOKIES, HttpServletResponse.SC_OK);
+    }
+
+    /*
+     * Test the optional behaviour of BASIC authentication to create
+     * a session on the server. The server will return a session cookie.
+     *
+     * 1. try to access a protected resource without credentials, so
+     *    get Unauthorized status.
+     * 2. try to access a protected resource when providing credentials,
+     *    so get OK status and a server session cookie.
+     * 3. access the protected resource once more using a session cookie.
+     * 4. repeat using the session cookie.
+     *
+     * Note: The FormAuthenticator is a two-step process and is protected
+     *       from session fixation attacks by the default AuthenticatorBase
+     *       changeSessionIdOnAuthentication setting of true. However,
+     *       BasicAuthenticator is a one-step process and so the
+     *       AuthenticatorBase does not reissue the sessionId.
+     */
+   @Test
+    public void testBasicLoginSessionPersistence() throws Exception {
+
+        setAlwaysUseSession();
+
+        // this section is identical to testAuthMethodCaseBasic
+        doTestBasic(USER, PWD, CONTEXT_PATH_LOGIN + URI_PROTECTED,
+                NO_CREDENTIALS, NO_COOKIES, HttpServletResponse.SC_UNAUTHORIZED);
+        doTestBasic(USER, PWD, CONTEXT_PATH_LOGIN + URI_PROTECTED,
+                GOOD_CREDENTIALS, NO_COOKIES, HttpServletResponse.SC_OK);
+
+        // confirm the session is not recognised by the server alone
+        doTestBasic(USER, PWD, CONTEXT_PATH_LOGIN + URI_PROTECTED,
+                NO_CREDENTIALS, NO_COOKIES, HttpServletResponse.SC_UNAUTHORIZED);
+
+        // now provide the harvested session cookie for authentication
+        doTestBasic(USER, PWD, CONTEXT_PATH_LOGIN + URI_PROTECTED,
+                NO_CREDENTIALS, USE_COOKIES, HttpServletResponse.SC_OK);
+
+        // finally, do it again with the cookie to be sure
+        doTestBasic(USER, PWD, CONTEXT_PATH_LOGIN + URI_PROTECTED,
+                NO_CREDENTIALS, USE_COOKIES, HttpServletResponse.SC_OK);
+    }
+
+    /*
+     * Verify the timeout mechanism works for BASIC sessions. This test
+     * follows the flow of testBasicLoginSessionPersistence (above).
+     */
+   @Test
     public void testBasicLoginSessionTimeout() throws Exception {
+
+       setAlwaysUseSession();
+
+       // this section is identical to testAuthMethodCaseBasic
+        doTestBasic(USER, PWD, CONTEXT_PATH_LOGIN + URI_PROTECTED,
+                NO_CREDENTIALS, NO_COOKIES, HttpServletResponse.SC_UNAUTHORIZED);
+        doTestBasic(USER, PWD, CONTEXT_PATH_LOGIN + URI_PROTECTED,
+                GOOD_CREDENTIALS, NO_COOKIES, HttpServletResponse.SC_OK);
+
+        // now provide the harvested session cookie for authentication
+        List<String> originalCookies = cookies;
+        doTestBasic(USER, PWD, CONTEXT_PATH_LOGIN + URI_PROTECTED,
+                NO_CREDENTIALS, USE_COOKIES, HttpServletResponse.SC_OK);
+
+        // allow the session to time out and lose authentication
+        Thread.sleep(TIMEOUT_DELAY_MSECS);
+
+        // provide the harvested session cookie for authentication
+        // to confirm it has expired
+        doTestBasic(USER, PWD, CONTEXT_PATH_LOGIN + URI_PROTECTED,
+                NO_CREDENTIALS, USE_COOKIES, HttpServletResponse.SC_UNAUTHORIZED);
+
+        // finally, do BASIC reauthentication and get another session
         doTestBasic(USER, PWD, CONTEXT_PATH_LOGIN + URI_PROTECTED,
-                false, true, 401, false, 200);
-        // wait long enough for the session above to expire
-        Thread.sleep(LONG_TIMEOUT_DELAY_MSECS);
+                NO_CREDENTIALS, NO_COOKIES, HttpServletResponse.SC_UNAUTHORIZED);
         doTestBasic(USER, PWD, CONTEXT_PATH_LOGIN + URI_PROTECTED,
-                false, true, 401, false, 200);
+                GOOD_CREDENTIALS, NO_COOKIES, HttpServletResponse.SC_OK);
+
+        // slightly paranoid verification
+        boolean sameCookies = originalCookies.equals(cookies);
+        assertTrue(!sameCookies);
     }
 
     /*
      * Logon to access a protected resource in a webapp that uses
      * BASIC authentication. Then try to access a protected resource
-     * in a different webapp that does not have a login method.
+     * in a different webapp which does not have a login method.
      * This should be rejected with SC_FORBIDDEN 403 status, confirming
      * there has been no cross-authentication between the webapps.
      */
     @Test
     public void testBasicLoginRejectProtected() throws Exception {
         doTestBasic(USER, PWD, CONTEXT_PATH_LOGIN + URI_PROTECTED,
-                false, true, 401, false, 200);
+                NO_CREDENTIALS, NO_COOKIES, HttpServletResponse.SC_UNAUTHORIZED);
+        doTestBasic(USER, PWD, CONTEXT_PATH_LOGIN + URI_PROTECTED,
+                GOOD_CREDENTIALS, NO_COOKIES, HttpServletResponse.SC_OK);
+
+        doTestNonLogin(CONTEXT_PATH_NOLOGIN + URI_PROTECTED,
+                NO_COOKIES, HttpServletResponse.SC_FORBIDDEN);
+    }
+
+    /*
+     * Try to use the session cookie from the BASIC webapp to request
+     * access to the webapp that does not have a login method. (This
+     * is equivalent to Single Signon, but without the Valve.)
+     *
+     * Verify there is no cross-authentication when using similar logic
+     * to testBasicLoginRejectProtected (above).
+     *
+     * This should be rejected with SC_FORBIDDEN 403 status.
+     */
+    @Test
+    public void testBasicLoginRejectProtectedWithSession() throws Exception {
+
+        setAlwaysUseSession();
+
+        doTestBasic(USER, PWD, CONTEXT_PATH_LOGIN + URI_PROTECTED,
+                NO_CREDENTIALS, NO_COOKIES, HttpServletResponse.SC_UNAUTHORIZED);
+        doTestBasic(USER, PWD, CONTEXT_PATH_LOGIN + URI_PROTECTED,
+                GOOD_CREDENTIALS, NO_COOKIES, HttpServletResponse.SC_OK);
+
+        // use the session cookie harvested with the other webapp
         doTestNonLogin(CONTEXT_PATH_NOLOGIN + URI_PROTECTED,
-                true, 403);
+                USE_COOKIES, HttpServletResponse.SC_FORBIDDEN);
     }
 
 
-    private void doTestNonLogin(String uri, boolean expectedReject,
+    private void doTestNonLogin(String uri, boolean useCookie,
             int expectedRC) throws Exception {
 
         Map<String,List<String>> reqHeaders = new HashMap<>();
         Map<String,List<String>> respHeaders = new HashMap<>();
 
+        if (useCookie && (cookies != null)) {
+            reqHeaders.put(CLIENT_COOKIE_HEADER + ":", cookies);
+        }
+
         ByteChunk bc = new ByteChunk();
         int rc = getUrl(HTTP_PREFIX + getPort() + uri, bc, reqHeaders,
                 respHeaders);
 
-        if (expectedReject) {
+        if (expectedRC != HttpServletResponse.SC_OK) {
             assertEquals(expectedRC, rc);
             assertTrue(bc.getLength() > 0);
         }
         else {
-            assertEquals(200, rc);
             assertEquals("OK", bc.toString());
         }
     }
 
     private void doTestBasic(String user, String pwd, String uri,
-            boolean verifyAuthSchemeCase,
-            boolean expectedReject1, int expectedRC1,
-            boolean expectedReject2, int expectedRC2) throws Exception {
-
-        // the first access attempt should be challenged
-        Map<String,List<String>> reqHeaders1 = new HashMap<>();
-        Map<String,List<String>> respHeaders1 = new HashMap<>();
+            BasicCredentials credentials, boolean useCookie,
+            int expectedRC) throws Exception {
 
-        ByteChunk bc = new ByteChunk();
-        int rc = getUrl(HTTP_PREFIX + getPort() + uri, bc, reqHeaders1,
-                respHeaders1);
+        Map<String,List<String>> reqHeaders = new HashMap<>();
+        Map<String,List<String>> respHeaders = new HashMap<>();
 
-        if (expectedReject1) {
-            assertEquals(expectedRC1, rc);
-            assertTrue(bc.getLength() > 0);
+        if (useCookie && (cookies != null)) {
+            reqHeaders.put(CLIENT_COOKIE_HEADER + ":", cookies);
         }
         else {
-            assertEquals(200, rc);
-            assertEquals("OK", bc.toString());
-            return;
+            if (credentials != null) {
+                List<String> auth = new ArrayList<>();
+                auth.add(credentials.getCredentials());
+                reqHeaders.put(CLIENT_AUTH_HEADER, auth);
+            }
         }
 
-        // the second access attempt should be sucessful
-        String credentials = user + ":" + pwd;
-        byte[] credentialsBytes = ByteChunk.convertToBytes(credentials);
-        String base64auth = Base64.encode(credentialsBytes);
-        String authScheme = verifyAuthSchemeCase ? "bAsIc " : "Basic ";
-        String authLine = authScheme + base64auth;
-
-        List<String> auth = new ArrayList<>();
-        auth.add(authLine);
-        Map<String,List<String>> reqHeaders2 = new HashMap<>();
-        reqHeaders2.put(CLIENT_AUTH_HEADER, auth);
-
-        Map<String,List<String>> respHeaders2 = new HashMap<>();
-
-        bc.recycle();
-        rc = getUrl(HTTP_PREFIX + getPort() + uri, bc, reqHeaders2,
-                respHeaders2);
+        ByteChunk bc = new ByteChunk();
+        int rc = getUrl(HTTP_PREFIX + getPort() + uri, bc, reqHeaders,
+                respHeaders);
 
-        if (expectedReject2) {
-            assertEquals(expectedRC2, rc);
+        if (expectedRC != HttpServletResponse.SC_OK) {
+            assertEquals(expectedRC, rc);
             assertTrue(bc.getLength() > 0);
+            if (expectedRC == HttpServletResponse.SC_UNAUTHORIZED) {
+                // The server should identify the acceptable method(s)
+                boolean methodFound = false;
+                List<String> authHeaders = respHeaders.get(SERVER_AUTH_HEADER);
+                for (String authHeader : authHeaders) {
+                    if (authHeader.indexOf(NICE_METHOD) > -1) {
+                        methodFound = true;
+                    }
+                }
+                assertTrue(methodFound);
+            }
         }
         else {
-            assertEquals(200, rc);
             assertEquals("OK", bc.toString());
+            List<String> newCookies = respHeaders.get(SERVER_COOKIE_HEADER);
+            if (newCookies != null) {
+                // harvest cookies whenever the server sends some new ones
+                cookies = newCookies;
+            }
         }
     }
 
 
+    /*
+     * setup two webapps for every test
+     *
+     * note: the super class tearDown method will stop tomcat
+     */
     @Override
     public void setUp() throws Exception {
 
         super.setUp();
 
         // create a tomcat server using the default in-memory Realm
-        Tomcat tomcat = getTomcatInstance();
+        tomcat = getTomcatInstance();
 
         // add the test user and role to the Realm
         tomcat.addUser(USER, PWD);
         tomcat.addRole(USER, ROLE);
 
         // setup both NonLogin and Login webapps
-        setUpNonLogin(tomcat);
-        setUpLogin(tomcat);
+        setUpNonLogin();
+        setUpLogin();
 
         tomcat.start();
     }
 
-    private void setUpNonLogin(Tomcat tomcat) throws Exception {
+
+    private void setUpNonLogin() throws Exception {
 
         // Must have a real docBase for webapps - just use temp
         Context ctxt = tomcat.addContext(CONTEXT_PATH_NOLOGIN,
                 System.getProperty("java.io.tmpdir"));
-        ctxt.setSessionTimeout(LONG_TIMEOUT_SECS);
+        ctxt.setSessionTimeout(LONG_TIMEOUT_MINS);
 
-        // Add protected servlet
+        // Add protected servlet to the context
         Tomcat.addServlet(ctxt, "TesterServlet1", new TesterServlet());
         ctxt.addServletMapping(URI_PROTECTED, "TesterServlet1");
 
@@ -261,7 +510,7 @@ public class TestNonLoginAndBasicAuthent
         sc1.addCollection(collection1);
         ctxt.addConstraint(sc1);
 
-        // Add unprotected servlet
+        // Add unprotected servlet to the context
         Tomcat.addServlet(ctxt, "TesterServlet2", new TesterServlet());
         ctxt.addServletMapping(URI_PUBLIC, "TesterServlet2");
 
@@ -276,17 +525,18 @@ public class TestNonLoginAndBasicAuthent
         LoginConfig lc = new LoginConfig();
         lc.setAuthMethod("NONE");
         ctxt.setLoginConfig(lc);
-        ctxt.getPipeline().addValve(new NonLoginAuthenticator());
+        nonloginAuthenticator = new NonLoginAuthenticator();
+        ctxt.getPipeline().addValve(nonloginAuthenticator);
     }
 
-    private void setUpLogin(Tomcat tomcat) throws Exception {
+    private void setUpLogin() throws Exception {
 
         // Must have a real docBase for webapps - just use temp
         Context ctxt = tomcat.addContext(CONTEXT_PATH_LOGIN,
                 System.getProperty("java.io.tmpdir"));
-        ctxt.setSessionTimeout(SHORT_TIMEOUT_SECS);
+        ctxt.setSessionTimeout(SHORT_TIMEOUT_MINS);
 
-        // Add protected servlet
+        // Add protected servlet to the context
         Tomcat.addServlet(ctxt, "TesterServlet3", new TesterServlet());
         ctxt.addServletMapping(URI_PROTECTED, "TesterServlet3");
         SecurityCollection collection = new SecurityCollection();
@@ -296,7 +546,7 @@ public class TestNonLoginAndBasicAuthent
         sc.addCollection(collection);
         ctxt.addConstraint(sc);
 
-        // Add unprotected servlet
+        // Add unprotected servlet to the context
         Tomcat.addServlet(ctxt, "TesterServlet4", new TesterServlet());
         ctxt.addServletMapping(URI_PUBLIC, "TesterServlet4");
 
@@ -311,7 +561,44 @@ public class TestNonLoginAndBasicAuthent
         LoginConfig lc = new LoginConfig();
         lc.setAuthMethod("BASIC");
         ctxt.setLoginConfig(lc);
-        ctxt.getPipeline().addValve(new BasicAuthenticator());
+        basicAuthenticator = new BasicAuthenticator();
+        ctxt.getPipeline().addValve(basicAuthenticator);
+    }
+
+    /*
+     * Force non-default behaviour for both Authenticators
+     */
+    private void setAlwaysUseSession() {
+
+        basicAuthenticator.setAlwaysUseSession(true);
+        nonloginAuthenticator.setAlwaysUseSession(true);
     }
 
+    /*
+     * Encapsulate the logic to generate an HTTP header
+     * for BASIC Authentication.
+     * Note: only used internally, so no need to validate arguments.
+     */
+    private static final class BasicCredentials {
+
+        private final String method;
+        private final String username;
+        private final String password;
+        private final String credentials;
+
+        private BasicCredentials(String aMethod,
+                String aUsername, String aPassword) {
+            method = aMethod;
+            username = aUsername;
+            password = aPassword;
+            String userCredentials = username + ":" + password;
+            byte[] credentialsBytes = ByteChunk.convertToBytes(userCredentials);
+            String base64auth = Base64.encode(credentialsBytes);
+            credentials= method + " " + base64auth;
+        }
+
+        private String getCredentials() {
+            return credentials;
+        }
+    }
 }
\ No newline at end of file



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org