ASF Bugzilla – Attachment 29621 Details for
Bug 54190
TestNonLoginAndBasicAuthenticator does not test session timeout properly
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Extensive update to the test class to demonstrate session timeout properly
TestNonLoginAndBasicAuthenticator.patch (text/plain), 19.13 KB, created by
Brian Burch
on 2012-11-22 13:10:23 UTC
(
hide
)
Description:
Extensive update to the test class to demonstrate session timeout properly
Filename:
MIME Type:
Creator:
Brian Burch
Created:
2012-11-22 13:10:23 UTC
Size:
19.13 KB
patch
obsolete
>Index: TestNonLoginAndBasicAuthenticator.java >=================================================================== >--- TestNonLoginAndBasicAuthenticator.java (revision 1406101) >+++ TestNonLoginAndBasicAuthenticator.java (working copy) >@@ -48,6 +48,20 @@ > */ > public class TestNonLoginAndBasicAuthenticator extends TomcatBaseTest { > >+ // these should really be singletons to be type-safe, >+ // we are in a unit test and don't need to paranoid. >+ protected static final Boolean EXPECT_REJECT = true; >+ protected static final Boolean EXPECT_ACCEPT = !EXPECT_REJECT; >+ >+ protected static final Boolean USE_COOKIES = true; >+ protected static final Boolean NO_COOKIES = !USE_COOKIES; >+ >+ protected static final Boolean PROVIDE_CREDENTIALS = true; >+ protected static final Boolean NO_CREDENTIALS = !PROVIDE_CREDENTIALS; >+ >+ protected static final Boolean VERIFY_AUTH_SCHEME = true; >+ protected static final Boolean NO_VERIFY_AUTH_SCHEME = !VERIFY_AUTH_SCHEME; >+ > private static final String USER = "user"; > private static final String PWD = "pwd"; > private static final String ROLE = "role"; >@@ -58,13 +72,20 @@ > 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 final int SHORT_TIMEOUT_MINS = 1; >+ private static final int LONG_TIMEOUT_MINS = 2; >+ private static final long TIMEOUT_DELAY_MSECS = >+ (((SHORT_TIMEOUT_MINS * 60) + 10) * 1000); > >- private static String CLIENT_AUTH_HEADER = "authorization"; >+ private static final String CLIENT_AUTH_HEADER = "authorization"; >+ private static final String SERVER_COOKIE_HEADER = "Set-Cookie"; >+ private static final String CLIENT_COOKIE_HEADER = "Cookie"; > >+ private Tomcat tomcat; >+ private AuthenticatorBase basicAuthenticator; >+ private AuthenticatorBase nonloginAuthenticator; >+ private List<String> cookies; >+ > /* > * Try to access an unprotected resource in a webapp that > * does not have a login method defined. >@@ -72,7 +93,8 @@ > */ > @Test > public void testAcceptPublicNonLogin() throws Exception { >- doTestNonLogin(CONTEXT_PATH_NOLOGIN + URI_PUBLIC, false, 200); >+ doTestNonLogin(CONTEXT_PATH_NOLOGIN + URI_PUBLIC, >+ NO_COOKIES, EXPECT_ACCEPT, 200); > } > > /* >@@ -82,7 +104,8 @@ > */ > @Test > public void testRejectProtectedNonLogin() throws Exception { >- doTestNonLogin(CONTEXT_PATH_NOLOGIN + URI_PROTECTED, true, 403); >+ doTestNonLogin(CONTEXT_PATH_NOLOGIN + URI_PROTECTED, >+ NO_COOKIES, EXPECT_REJECT, 403); > } > > /* >@@ -93,7 +116,8 @@ > @Test > public void testAcceptPublicBasic() throws Exception { > doTestBasic(USER, PWD, CONTEXT_PATH_LOGIN + URI_PUBLIC, >- false, false, 200, false, 200); >+ NO_VERIFY_AUTH_SCHEME, NO_CREDENTIALS, NO_COOKIES, >+ EXPECT_ACCEPT, 200); > } > > /* >@@ -104,7 +128,11 @@ > @Test > public void testAcceptProtectedBasic() throws Exception { > doTestBasic(USER, PWD, CONTEXT_PATH_LOGIN + URI_PROTECTED, >- false, true, 401, false, 200); >+ NO_VERIFY_AUTH_SCHEME, NO_CREDENTIALS, NO_COOKIES, >+ EXPECT_REJECT, 401); >+ doTestBasic(USER, PWD, CONTEXT_PATH_LOGIN + URI_PROTECTED, >+ NO_VERIFY_AUTH_SCHEME, PROVIDE_CREDENTIALS, NO_COOKIES, >+ EXPECT_ACCEPT, 200); > } > > /* >@@ -116,24 +144,123 @@ > @Test > public void testAuthMethodCaseBasic() throws Exception { > doTestBasic(USER, PWD, CONTEXT_PATH_LOGIN + URI_PROTECTED, >- true, true, 401, false, 200); >+ VERIFY_AUTH_SCHEME, NO_CREDENTIALS, NO_COOKIES, >+ EXPECT_REJECT, 401); >+ doTestBasic(USER, PWD, CONTEXT_PATH_LOGIN + URI_PROTECTED, >+ VERIFY_AUTH_SCHEME, PROVIDE_CREDENTIALS, NO_COOKIES, >+ EXPECT_ACCEPT, 200); > } > > /* >+ * Test the default behaviour of BASIC authentication, which does >+ * NOT create a session on the server. The authentication must be >+ * performed by the browser sending a valid authenticate header >+ * with every request for a protected resource. >+ * > * 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. >+ * BASIC authentication. Immediately try to re-access the resource >+ * without providing credentials. This should be rejected with >+ * SC_FORBIDDEN 401 status, which can be followed by successful >+ * re-authentication. > */ > @Test >+ public void testBasicLoginWithoutSession() throws Exception { >+ doTestBasic(USER, PWD, CONTEXT_PATH_LOGIN + URI_PROTECTED, >+ NO_VERIFY_AUTH_SCHEME, NO_CREDENTIALS, NO_COOKIES, >+ EXPECT_REJECT, 401); >+ doTestBasic(USER, PWD, CONTEXT_PATH_LOGIN + URI_PROTECTED, >+ NO_VERIFY_AUTH_SCHEME, PROVIDE_CREDENTIALS, NO_COOKIES, >+ EXPECT_ACCEPT, 200); >+ >+ // next, don't provide credentials initially >+ doTestBasic(USER, PWD, CONTEXT_PATH_LOGIN + URI_PROTECTED, >+ NO_VERIFY_AUTH_SCHEME, NO_CREDENTIALS, NO_COOKIES, >+ EXPECT_REJECT, 401); >+ doTestBasic(USER, PWD, CONTEXT_PATH_LOGIN + URI_PROTECTED, >+ NO_VERIFY_AUTH_SCHEME, PROVIDE_CREDENTIALS, NO_COOKIES, >+ EXPECT_ACCEPT, 200); >+ } >+ >+ /* >+ * 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 AuthenticatorBase >+ * changeSessionIdOnAuthentication default 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(); >+ doTestBasic(USER, PWD, CONTEXT_PATH_LOGIN + URI_PROTECTED, >+ NO_VERIFY_AUTH_SCHEME, NO_CREDENTIALS, NO_COOKIES, >+ EXPECT_REJECT, 401); >+ doTestBasic(USER, PWD, CONTEXT_PATH_LOGIN + URI_PROTECTED, >+ NO_VERIFY_AUTH_SCHEME, PROVIDE_CREDENTIALS, NO_COOKIES, >+ EXPECT_ACCEPT, 200); >+ doTestBasic(USER, PWD, CONTEXT_PATH_LOGIN + URI_PROTECTED, >+ NO_VERIFY_AUTH_SCHEME, PROVIDE_CREDENTIALS, USE_COOKIES, >+ EXPECT_ACCEPT, 200); >+ doTestBasic(USER, PWD, CONTEXT_PATH_LOGIN + URI_PROTECTED, >+ NO_VERIFY_AUTH_SCHEME, PROVIDE_CREDENTIALS, USE_COOKIES, >+ EXPECT_ACCEPT, 200); >+ } >+ >+ /* >+ * Test the optional behaviour of BASIC authentication to create >+ * a session on the server. The server will return a session cookie. >+ * Verify the session timeout mechanism. >+ * >+ * 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. wait long enough for the session to time out. >+ * 5. try to access the protected resource once more using the >+ * original session cookie. It should be rejected as Unauthorized. >+ * 6. try to access the protected resource when providing credentials, >+ * so get OK status and a new server session cookie. >+ * 7. access the protected resource once more using the new session cookie. >+ */ >+ @Test > public void testBasicLoginSessionTimeout() throws Exception { >+ setAlwaysUseSession(); > 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_VERIFY_AUTH_SCHEME, NO_CREDENTIALS, NO_COOKIES, >+ EXPECT_REJECT, 401); > doTestBasic(USER, PWD, CONTEXT_PATH_LOGIN + URI_PROTECTED, >- false, true, 401, false, 200); >+ NO_VERIFY_AUTH_SCHEME, PROVIDE_CREDENTIALS, NO_COOKIES, >+ EXPECT_ACCEPT, 200); >+ doTestBasic(USER, PWD, CONTEXT_PATH_LOGIN + URI_PROTECTED, >+ NO_VERIFY_AUTH_SCHEME, PROVIDE_CREDENTIALS, USE_COOKIES, >+ EXPECT_ACCEPT, 200); >+ >+ // allow the session to time out and lose authentication >+ List<String> originalCookies = cookies; >+ Thread.sleep(TIMEOUT_DELAY_MSECS); >+ doTestBasic(USER, PWD, CONTEXT_PATH_LOGIN + URI_PROTECTED, >+ NO_VERIFY_AUTH_SCHEME, PROVIDE_CREDENTIALS, USE_COOKIES, >+ EXPECT_REJECT, 401); >+ doTestBasic(USER, PWD, CONTEXT_PATH_LOGIN + URI_PROTECTED, >+ NO_VERIFY_AUTH_SCHEME, PROVIDE_CREDENTIALS, NO_COOKIES, >+ EXPECT_ACCEPT, 200); >+ doTestBasic(USER, PWD, CONTEXT_PATH_LOGIN + URI_PROTECTED, >+ NO_VERIFY_AUTH_SCHEME, PROVIDE_CREDENTIALS, USE_COOKIES, >+ EXPECT_ACCEPT, 200); >+ >+ // slightly paranoid verification >+ boolean sameCookies = originalCookies.equals(cookies); >+ assertTrue(!sameCookies); > } > > /* >@@ -146,18 +273,47 @@ > @Test > public void testBasicLoginRejectProtected() throws Exception { > doTestBasic(USER, PWD, CONTEXT_PATH_LOGIN + URI_PROTECTED, >- false, true, 401, false, 200); >+ NO_VERIFY_AUTH_SCHEME, NO_CREDENTIALS, NO_COOKIES, >+ EXPECT_REJECT, 401); >+ doTestBasic(USER, PWD, CONTEXT_PATH_LOGIN + URI_PROTECTED, >+ NO_VERIFY_AUTH_SCHEME, PROVIDE_CREDENTIALS, NO_COOKIES, >+ EXPECT_ACCEPT, 200); > doTestNonLogin(CONTEXT_PATH_NOLOGIN + URI_PROTECTED, >- true, 403); >+ NO_COOKIES, EXPECT_REJECT, 403); > } > >+ /* >+ * Logon to access a protected resource in a webapp that uses >+ * BASIC authentication and session id. Then try to access a >+ * protected resource in a different webapp that does not have >+ * a login method using the original session. >+ * This should be rejected with SC_FORBIDDEN 403 status, confirming >+ * there has been no cross-authentication between the webapps. >+ */ >+ @Test >+ public void testBasicLoginRejectProtectedWithSession() throws Exception { >+ setAlwaysUseSession(); >+ doTestBasic(USER, PWD, CONTEXT_PATH_LOGIN + URI_PROTECTED, >+ NO_VERIFY_AUTH_SCHEME, NO_CREDENTIALS, NO_COOKIES, >+ EXPECT_REJECT, 401); >+ doTestBasic(USER, PWD, CONTEXT_PATH_LOGIN + URI_PROTECTED, >+ NO_VERIFY_AUTH_SCHEME, PROVIDE_CREDENTIALS, NO_COOKIES, >+ EXPECT_ACCEPT, 200); >+ doTestNonLogin(CONTEXT_PATH_NOLOGIN + URI_PROTECTED, >+ USE_COOKIES, EXPECT_REJECT, 403); >+ } > >- private void doTestNonLogin(String uri, boolean expectedReject, >- int expectedRC) throws Exception { > >+ private void doTestNonLogin(String uri, boolean useCookie, >+ boolean expectedReject, 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); >@@ -173,84 +329,83 @@ > } > > private void doTestBasic(String user, String pwd, String uri, >- boolean verifyAuthSchemeCase, >- boolean expectedReject1, int expectedRC1, >- boolean expectedReject2, int expectedRC2) throws Exception { >+ boolean verifyAuthSchemeCase, boolean provideCredentials, >+ boolean useCookie, boolean expectedReject, int expectedRC) >+ throws Exception { > >- // the first access attempt should be challenged >- Map<String,List<String>> reqHeaders1 = new HashMap<>(); >- Map<String,List<String>> respHeaders1 = new HashMap<>(); >+ Map<String,List<String>> reqHeaders = new HashMap<>(); >+ Map<String,List<String>> respHeaders = new HashMap<>(); > >- ByteChunk bc = new ByteChunk(); >- int rc = getUrl(HTTP_PREFIX + getPort() + uri, bc, reqHeaders1, >- respHeaders1); >+ if (provideCredentials) { >+ if (useCookie && (cookies != null)) { >+ reqHeaders.put(CLIENT_COOKIE_HEADER + ":", cookies); >+ } >+ else { >+ String credentials = user + ":" + pwd; >+ byte[] credentialsBytes = ByteChunk.convertToBytes(credentials); >+ String base64auth = Base64.encode(credentialsBytes); >+ String authScheme = verifyAuthSchemeCase ? "bAsIc " : "Basic "; >+ String authLine = authScheme + base64auth; > >- if (expectedReject1) { >- assertEquals(expectedRC1, rc); >- assertTrue(bc.getLength() > 0); >+ List<String> auth = new ArrayList<>(); >+ auth.add(authLine); >+ reqHeaders.put(CLIENT_AUTH_HEADER, auth); >+ } > } >- else { >- assertEquals(200, rc); >- assertEquals("OK", bc.toString()); >- return; >- } > >- // 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; >+ ByteChunk bc = new ByteChunk(); >+ int rc = getUrl(HTTP_PREFIX + getPort() + uri, bc, reqHeaders, >+ respHeaders); > >- 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); >- >- if (expectedReject2) { >- assertEquals(expectedRC2, rc); >+ if (expectedReject) { >+ assertEquals(expectedRC, rc); > assertTrue(bc.getLength() > 0); > } > 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 +416,7 @@ > 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 +431,18 @@ > 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 +452,7 @@ > 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 +467,17 @@ > 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); >+ } >+ > } >\ No newline at end of file
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 54190
:
29621
|
29641
|
29642
|
29669