fixed bug #824791: Session not invalidated upon re-authentication
authormaxcooper <maxcooper>
Sat, 25 Oct 2003 10:49:03 +0000 (10:49 +0000)
committermaxcooper <maxcooper>
Sat, 25 Oct 2003 10:49:03 +0000 (10:49 +0000)
added test to make sure it stays fixed

src/example/org/securityfilter/example/Constants.java
src/example/org/securityfilter/example/realm/TrivialSecurityRealm.java
src/share/org/securityfilter/authenticator/FormAuthenticator.java
src/test/org/securityfilter/test/http/form/PostMethodTest.java
src/test/org/securityfilter/test/http/form/SessionInvalidationTest.java [new file with mode: 0644]
web/share/securePage.jsp

index 0fa4ebd..e3f6f8c 100644 (file)
@@ -1,7 +1,7 @@
 /*
- * $Header: /cvsroot/securityfilter/securityfilter/src/example/org/securityfilter/example/Constants.java,v 1.3 2003/06/14 14:10:42 maxcooper Exp $
- * $Revision: 1.3 $
- * $Date: 2003/06/14 14:10:42 $
+ * $Header: /cvsroot/securityfilter/securityfilter/src/example/org/securityfilter/example/Constants.java,v 1.4 2003/10/25 10:49:04 maxcooper Exp $
+ * $Revision: 1.4 $
+ * $Date: 2003/10/25 10:49:04 $
  *
  * ====================================================================
  * The SecurityFilter Software License, Version 1.1
@@ -59,7 +59,7 @@ package org.securityfilter.example;
  * Constants - constants for the example applications to facilitate testing
  *
  * @author Max Cooper (max@maxcooper.com)
- * @version $Revision: 1.3 $ $Date: 2003/06/14 14:10:42 $
+ * @version $Revision: 1.4 $ $Date: 2003/10/25 10:49:04 $
  */
 public interface Constants {
 
@@ -67,6 +67,8 @@ public interface Constants {
    public static final String COMMON_TITLE_BASE = "SecurityFilter Example Application: ";
    public static final String VALID_USERNAME = "username";
    public static final String VALID_PASSWORD = "password";
+   public static final String VALID_USERNAME2 = "username2";
+   public static final String VALID_PASSWORD2 = "password2";
    public static final String VALID_ROLE = "inthisrole";
 
    // home page constants
@@ -83,7 +85,9 @@ public interface Constants {
 
    // secure page constants
    public static final String SECURE_TITLE = COMMON_TITLE_BASE + "Secure Page";
-   public static final String SECURE_POSTED_VALUE_ID = "postedValue";
+   public static final String SECURE_POSTED_VALUE_FORM = "postedValueForm";
+   public static final String SECURE_POSTED_VALUE_FIELD = "postedValue";
+   public static final String SECURE_LAST_POSTED_VALUE_FIELD = "lastPostedValue";
 
    // logout page constants
    public static final String LOGOUT_TITLE = COMMON_TITLE_BASE + "Logout";
index b7a98d6..eba0718 100644 (file)
@@ -1,7 +1,7 @@
 /*
- * $Header: /cvsroot/securityfilter/securityfilter/src/example/org/securityfilter/example/realm/TrivialSecurityRealm.java,v 1.2 2003/06/14 14:39:03 maxcooper Exp $
- * $Revision: 1.2 $
- * $Date: 2003/06/14 14:39:03 $
+ * $Header: /cvsroot/securityfilter/securityfilter/src/example/org/securityfilter/example/realm/TrivialSecurityRealm.java,v 1.3 2003/10/25 10:49:04 maxcooper Exp $
+ * $Revision: 1.3 $
+ * $Date: 2003/10/25 10:49:04 $
  *
  * ====================================================================
  * The SecurityFilter Software License, Version 1.1
@@ -65,7 +65,7 @@ import org.securityfilter.realm.SimpleSecurityRealmBase;
  * And this user is in one role: 'inthisrole'
  *
  * @author Max Cooper (max@maxcooper.com)
- * @version $Revision: 1.2 $ $Date: 2003/06/14 14:39:03 $
+ * @version $Revision: 1.3 $ $Date: 2003/10/25 10:49:04 $
  */
 public class TrivialSecurityRealm extends SimpleSecurityRealmBase {
 
@@ -82,7 +82,10 @@ public class TrivialSecurityRealm extends SimpleSecurityRealmBase {
     * @return null if the user cannot be authenticated, otherwise a Pricipal object is returned
     */
    public boolean booleanAuthenticate(String username, String password) {
-      return Constants.VALID_USERNAME.equals(username) && Constants.VALID_PASSWORD.equals(password);
+      return (
+         (Constants.VALID_USERNAME.equals(username) && Constants.VALID_PASSWORD.equals(password))
+         || (Constants.VALID_USERNAME2.equals(username) && Constants.VALID_PASSWORD2.equals(password))
+      );
    }
 
    /**
@@ -95,7 +98,10 @@ public class TrivialSecurityRealm extends SimpleSecurityRealmBase {
     * @return true if the user is in the role, false otherwise
     */
    public boolean isUserInRole(String username, String role) {
-      return Constants.VALID_USERNAME.equals(username) && Constants.VALID_ROLE.equals(role);
+      return (
+         (Constants.VALID_USERNAME.equals(username) || Constants.VALID_USERNAME2.equals(username))
+         && Constants.VALID_ROLE.equals(role)
+      );
    }
 
    /**
index 7b4204a..aa1fe2c 100644 (file)
@@ -1,7 +1,7 @@
 /*
- * $Header: /cvsroot/securityfilter/securityfilter/src/share/org/securityfilter/authenticator/FormAuthenticator.java,v 1.1 2003/07/07 13:12:56 maxcooper Exp $
- * $Revision: 1.1 $
- * $Date: 2003/07/07 13:12:56 $
+ * $Header: /cvsroot/securityfilter/securityfilter/src/share/org/securityfilter/authenticator/FormAuthenticator.java,v 1.2 2003/10/25 10:49:03 maxcooper Exp $
+ * $Revision: 1.2 $
+ * $Date: 2003/10/25 10:49:03 $
  *
  * ====================================================================
  * The SecurityFilter Software License, Version 1.1
@@ -68,7 +68,7 @@ import java.security.Principal;
  * FormAuthenticator - authenticator implementation for the FORM auth method.
  *
  * @author Max Cooper (max@maxcooper.com)
- * @version $Revision: 1.1 $ $Date: 2003/07/07 13:12:56 $
+ * @version $Revision: 1.2 $ $Date: 2003/10/25 10:49:03 $
  */
 public class FormAuthenticator implements Authenticator {
 
@@ -144,9 +144,12 @@ public class FormAuthenticator implements Authenticator {
          Principal principal = realm.authenticate(username, password);
          if (principal != null) {
             // login successful
-            // invalidate old session if the user was already authenticated
-            // NOTE: we may want to check if the user re-authenticated as the same user, currently
-            // the session will be invalidated even if the user authenticates as the same user.
+
+            // invalidate old session if the user was already authenticated, and they logged in as a different user
+            if (request.getUserPrincipal() != null && !username.equals(request.getRemoteUser())) {
+               request.getSession().invalidate();
+            }
+
             request.setUserPrincipal(principal);
             String continueToURL = getContinueToURL(request);
             // This is the url that the user was initially accessing before being prompted for login.
index d259125..3f8d9c2 100644 (file)
@@ -1,7 +1,7 @@
 /*
- * $Header: /cvsroot/securityfilter/securityfilter/src/test/org/securityfilter/test/http/form/PostMethodTest.java,v 1.3 2003/07/07 13:14:07 maxcooper Exp $
- * $Revision: 1.3 $
- * $Date: 2003/07/07 13:14:07 $
+ * $Header: /cvsroot/securityfilter/securityfilter/src/test/org/securityfilter/test/http/form/PostMethodTest.java,v 1.4 2003/10/25 10:49:03 maxcooper Exp $
+ * $Revision: 1.4 $
+ * $Date: 2003/10/25 10:49:03 $
  *
  * ====================================================================
  * The SecurityFilter Software License, Version 1.1
@@ -60,10 +60,10 @@ import org.securityfilter.example.Constants;
 import org.securityfilter.test.http.TestBase;
 
 /**
- * LogoutTest - tests the logout functionality.
+ * PostMethodTest - tests that POSTed parameters are maintained through an authentication sequence.
  *
  * @author Max Cooper (max@maxcooper.com)
- * @version $Revision: 1.3 $ $Date: 2003/07/07 13:14:07 $
+ * @version $Revision: 1.4 $ $Date: 2003/10/25 10:49:03 $
  */
 public class PostMethodTest extends TestBase {
    private static final String POST_VALUE = "it works!";
@@ -83,7 +83,7 @@ public class PostMethodTest extends TestBase {
     * @throws Exception
     */
    public void testKeepPostedParametersThroughLogin() throws Exception {
-      // load the Home page to get the session manipulation form
+      // load the Home page to get the POST input form
       WebRequest request = new GetMethodWebRequest(baseUrl + "/index.jsp");
       WebResponse response = session.getResponse(request);
 
@@ -104,8 +104,9 @@ public class PostMethodTest extends TestBase {
       assertPageTitle(response, Constants.SECURE_TITLE);
 
       // make sure the item we submitted is present
-      TableCell postedValue = (TableCell) response.getElementWithID(Constants.SECURE_POSTED_VALUE_ID);
+      WebForm form = response.getFormWithName(Constants.SECURE_POSTED_VALUE_FORM);
+      String postedValue = form.getParameterValue(Constants.SECURE_POSTED_VALUE_FIELD);
       assertNotNull("POSTed parameter not found in reponse", postedValue);
-      assertEquals("POSTed parameter did not have the right value", postedValue.asText(), POST_VALUE);
+      assertEquals("POSTed parameter did not have the right value", postedValue, POST_VALUE);
    }
 }
diff --git a/src/test/org/securityfilter/test/http/form/SessionInvalidationTest.java b/src/test/org/securityfilter/test/http/form/SessionInvalidationTest.java
new file mode 100644 (file)
index 0000000..5512e8f
--- /dev/null
@@ -0,0 +1,173 @@
+/*
+ * $Header: /cvsroot/securityfilter/securityfilter/src/test/org/securityfilter/test/http/form/SessionInvalidationTest.java,v 1.1 2003/10/25 10:49:03 maxcooper Exp $
+ * $Revision: 1.1 $
+ * $Date: 2003/10/25 10:49:03 $
+ *
+ * ====================================================================
+ * The SecurityFilter Software License, Version 1.1
+ *
+ * (this license is derived and fully compatible with the Apache Software
+ * License - see http://www.apache.org/LICENSE.txt)
+ *
+ * Copyright (c) 2002 SecurityFilter.org. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ *    if any, must include the following acknowledgment:
+ *       "This product includes software developed by
+ *        SecurityFilter.org (http://www.securityfilter.org/)."
+ *    Alternately, this acknowledgment may appear in the software itself,
+ *    if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The name "SecurityFilter" must not be used to endorse or promote
+ *    products derived from this software without prior written permission.
+ *    For written permission, please contact license@securityfilter.org .
+ *
+ * 5. Products derived from this software may not be called "SecurityFilter",
+ *    nor may "SecurityFilter" appear in their name, without prior written
+ *    permission of SecurityFilter.org.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE SECURITY FILTER PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ */
+
+package org.securityfilter.test.http.form;
+
+import com.meterware.httpunit.*;
+import org.securityfilter.example.Constants;
+import org.securityfilter.test.http.TestBase;
+
+/**
+ * SessionInvalidationTest - tests the logout functionality.
+ *
+ * @author Max Cooper (max@maxcooper.com)
+ * @version $Revision: 1.1 $ $Date: 2003/10/25 10:49:03 $
+ */
+public class SessionInvalidationTest extends TestBase {
+   private static final String POST_VALUE_1 = "post1";
+   private static final String POST_VALUE_2 = "post2";
+
+   /**
+    * Constructor
+    *
+    * @param name
+    */
+   public SessionInvalidationTest(String name) {
+      super(name);
+   }
+
+   /**
+    * Test that the session is kept if the user spontaneously logs in again with the same username.
+    *
+    * @throws Exception
+    */
+   public void testKeepSessionForSameUser() throws Exception {
+
+      // login
+      WebConversation session = new WebConversation();
+      WebRequest request = new PostMethodWebRequest(baseUrl + "/j_security_check");
+      request.setParameter(Constants.LOGIN_USERNAME_FIELD, Constants.VALID_USERNAME);
+      request.setParameter(Constants.LOGIN_PASSWORD_FIELD, Constants.VALID_PASSWORD);
+      WebResponse response = session.getResponse(request);
+
+      // post the first value
+      request = new GetMethodWebRequest(baseUrl + "/index.jsp");
+      response = session.getResponse(request);
+      WebForm sessionForm = response.getFormWithID(Constants.HOME_FORM_ID);
+      sessionForm.setParameter(Constants.HOME_POST_FIELD, POST_VALUE_1);
+      response = sessionForm.submit();
+
+      // login again as the same user in the same session
+      request = new PostMethodWebRequest(baseUrl + "/j_security_check");
+      request.setParameter(Constants.LOGIN_USERNAME_FIELD, Constants.VALID_USERNAME);
+      request.setParameter(Constants.LOGIN_PASSWORD_FIELD, Constants.VALID_PASSWORD);
+      response = session.getResponse(request);
+
+      // post the second value
+      request = new GetMethodWebRequest(baseUrl + "/index.jsp");
+      response = session.getResponse(request);
+      sessionForm = response.getFormWithID(Constants.HOME_FORM_ID);
+      sessionForm.setParameter(Constants.HOME_POST_FIELD, POST_VALUE_2);
+      response = sessionForm.submit();
+
+      // make sure the response leads us to secure page
+      assertPageTitle(response, Constants.SECURE_TITLE);
+
+      // ensure that both the first and second POSTed values appear on the secure page
+      WebForm form = response.getFormWithName(Constants.SECURE_POSTED_VALUE_FORM);
+      String firstPostedValue = form.getParameterValue(Constants.SECURE_LAST_POSTED_VALUE_FIELD);
+      assertNotNull("First POSTed parameter not found in reponse", firstPostedValue);
+      assertEquals("First POSTed parameter did not have the right value", firstPostedValue, POST_VALUE_1);
+      String secondPostedValue = form.getParameterValue(Constants.SECURE_POSTED_VALUE_FIELD);
+      assertNotNull("Second POSTed parameter not found in reponse", secondPostedValue);
+      assertEquals("Second POSTed parameter did not have the right value", secondPostedValue, POST_VALUE_2);
+   }
+
+   /**
+    * Test that the session is invalidated if the user spontaneously logs in again with a different username.
+    *
+    * @throws Exception
+    */
+   public void testInvaidateSessionForDifferentUser() throws Exception {
+
+      // login
+      WebConversation session = new WebConversation();
+      WebRequest request = new PostMethodWebRequest(baseUrl + "/j_security_check");
+      request.setParameter(Constants.LOGIN_USERNAME_FIELD, Constants.VALID_USERNAME);
+      request.setParameter(Constants.LOGIN_PASSWORD_FIELD, Constants.VALID_PASSWORD);
+      WebResponse response = session.getResponse(request);
+
+      // post the first value
+      request = new GetMethodWebRequest(baseUrl + "/index.jsp");
+      response = session.getResponse(request);
+      WebForm sessionForm = response.getFormWithID(Constants.HOME_FORM_ID);
+      sessionForm.setParameter(Constants.HOME_POST_FIELD, POST_VALUE_1);
+      response = sessionForm.submit();
+
+      // login again as a different user in the same session
+      request = new PostMethodWebRequest(baseUrl + "/j_security_check");
+      request.setParameter(Constants.LOGIN_USERNAME_FIELD, Constants.VALID_USERNAME2);
+      request.setParameter(Constants.LOGIN_PASSWORD_FIELD, Constants.VALID_PASSWORD2);
+      response = session.getResponse(request);
+
+      // post the second value
+      request = new GetMethodWebRequest(baseUrl + "/index.jsp");
+      response = session.getResponse(request);
+      sessionForm = response.getFormWithID(Constants.HOME_FORM_ID);
+      sessionForm.setParameter(Constants.HOME_POST_FIELD, POST_VALUE_2);
+      response = sessionForm.submit();
+
+      // make sure the response leads us to secure page
+      assertPageTitle(response, Constants.SECURE_TITLE);
+
+      // ensure that both the first and second POSTed values appear on the secure page
+      WebForm form = response.getFormWithName(Constants.SECURE_POSTED_VALUE_FORM);
+      String firstPostedValue = form.getParameterValue(Constants.SECURE_LAST_POSTED_VALUE_FIELD);
+      assertNull("First POSTed parameter found in response, but it shouldn't be there", firstPostedValue);
+      String secondPostedValue = form.getParameterValue(Constants.SECURE_POSTED_VALUE_FIELD);
+      assertNotNull("Second POSTed parameter not found in reponse", secondPostedValue);
+      assertEquals("Second POSTed parameter did not have the right value", secondPostedValue, POST_VALUE_2);
+   }
+}
index 6fcc792..7163626 100644 (file)
@@ -18,12 +18,31 @@ Welcome <i><%=request.getRemoteUser()%></i>, you are viewing a secure page.
    if (postedValue != null) {
 %>
 <h2>You POSTed a value from the Home Page!</h2>
-The value you posted was:
-<table>
-   <tr>
-      <td id="<%=Constants.SECURE_POSTED_VALUE_ID%>"><%=postedValue%></td>
-   </tr>
-</table>
+<form name="<%=Constants.SECURE_POSTED_VALUE_FORM%>" action="">
+The value you just posted was:
+<ul>
+   <li>
+      <%=postedValue%>
+      <input type="hidden" name="<%=Constants.SECURE_POSTED_VALUE_FIELD%>" value="<%=postedValue%>"/>
+   </li>
+</ul>
+<%
+      String lastPostedValue = (String) session.getAttribute(Constants.SECURE_LAST_POSTED_VALUE_FIELD);
+      if (lastPostedValue != null) {
+%>
+The last value you posted in your current session was:
+<ul>
+   <li>
+      <%=lastPostedValue%>
+      <input type="hidden" name="<%=Constants.SECURE_LAST_POSTED_VALUE_FIELD%>" value="<%=lastPostedValue%>"/>
+   </li>
+</ul>
+<%
+      }
+      // save the last posted value in the session
+      session.setAttribute(Constants.SECURE_LAST_POSTED_VALUE_FIELD, postedValue);
+%>
+</form>
 <%
    }
 %>