Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=3839
authormarkt <markt@13f79535-47bb-0310-9956-ffa450edef68>
Wed, 20 Oct 2010 21:55:30 +0000 (21:55 +0000)
committermarkt <markt@13f79535-47bb-0310-9956-ffa450edef68>
Wed, 20 Oct 2010 21:55:30 +0000 (21:55 +0000)
Provide a mechanism to gracefully handle the case where users book-mark the form login page or otherwise abuse the FORM authentication process.
Based on a suggestion by Mark Morris.

git-svn-id: https://svn.apache.org/repos/asf/tomcat/trunk@1025775 13f79535-47bb-0310-9956-ffa450edef68

java/org/apache/catalina/authenticator/FormAuthenticator.java
webapps/docs/changelog.xml
webapps/docs/config/valve.xml

index f8ed35c..5b57e22 100644 (file)
@@ -75,6 +75,12 @@ public class FormAuthenticator
      */
     protected String characterEncoding = null;
 
+    /**
+     * Landing page to use if a user tries to access the login page directly or
+     * if the session times out during login. If not set, error responses will
+     * be sent instead.
+     */
+    protected String landingPage = null;
 
     // ------------------------------------------------------------- Properties
 
@@ -106,6 +112,22 @@ public class FormAuthenticator
     }
 
 
+    /**
+     * Return the landing page to use when FORM auth is mis-used.
+     */
+    public String getLandingPage() {
+        return landingPage;
+    }
+
+
+    /**
+     * Set the landing page to use when the FORM auth is mis-used.
+     */
+    public void setLandingPage(String landingPage) {
+        this.landingPage = landingPage;
+    }
+
+
     // --------------------------------------------------------- Public Methods
 
 
@@ -273,8 +295,19 @@ public class FormAuthenticator
             if (containerLog.isDebugEnabled())
                 containerLog.debug
                     ("User took so long to log on the session expired");
-            response.sendError(HttpServletResponse.SC_REQUEST_TIMEOUT,
-                               sm.getString("authenticator.sessionExpired"));
+            if (landingPage == null) {
+                response.sendError(HttpServletResponse.SC_REQUEST_TIMEOUT,
+                        sm.getString("authenticator.sessionExpired"));
+            } else {
+                // Make the authenticator think the user originally requested
+                // the landing page
+                String uri = request.getContextPath() + landingPage;
+                SavedRequest saved = new SavedRequest();
+                saved.setRequestURI(uri);
+                request.getSessionInternal(true).setNote(
+                        Constants.FORM_REQUEST_NOTE, saved);
+                response.sendRedirect(response.encodeRedirectURL(uri));
+            }
             return (false);
         }
 
@@ -291,8 +324,18 @@ public class FormAuthenticator
         if (log.isDebugEnabled())
             log.debug("Redirecting to original '" + requestURI + "'");
         if (requestURI == null)
-            response.sendError(HttpServletResponse.SC_BAD_REQUEST,
-                               sm.getString("authenticator.formlogin"));
+            if (landingPage == null) {
+                response.sendError(HttpServletResponse.SC_BAD_REQUEST,
+                        sm.getString("authenticator.formlogin"));
+            } else {
+                // Make the authenticator think the user originally requested
+                // the landing page
+                String uri = request.getContextPath() + landingPage;
+                SavedRequest saved = new SavedRequest();
+                saved.setRequestURI(uri);
+                session.setNote(Constants.FORM_REQUEST_NOTE, saved);
+                response.sendRedirect(response.encodeRedirectURL(uri));
+            }
         else
             response.sendRedirect(response.encodeRedirectURL(requestURI));
         return (false);
index 175c0db..68d8626 100644 (file)
   <subsection name="Catalina">
     <changelog>
       <fix>
+        <bug>3839</bug>: Provide a mechanism to gracefully handle the case where
+        users book-mark the form login page or otherwise misuse the FORM
+        authentication process. Based on a suggestion by Mark Morris. (markt)
+      </fix>
+      <fix>
         <bug>49991</bug>: Ensure servlet request listeners are fired for
         the login and error pages during FORM authentication. (markt)
       </fix>
index d4d3a9c..a4dc5a7 100644 (file)
         workaround for browser caching issues. If not set, the default value of
         <code>true</code> will be used.</p>
       </attribute>
+      
+      <attribute name="landingPage" required="false">
+        <p>Controls the behavior of the FORM authentication process if the
+        process is misused, for example by directly requesting the login page
+        or delaying logging in for so long that the session expires. If this
+        attribute is set, rather than returning an error response code, Tomcat
+        will redirect the user to the specified landing page if the login form
+        is submitted with valid credentials. For the login to be processed, the
+        landing page must be a protected resource (i.e. one that requires
+        authentication). If the landing page does not require authentication
+        then the user will not be logged in and will be prompted for their
+        credentials again when they access a protected page.</p>
+      </attribute>
 
       <attribute name="securePagesWithPragma" required="false">
         <p>Controls the caching of pages that are protected by security