got it working again after refactoring out into separate class
authormaxcooper <maxcooper>
Mon, 14 Jul 2003 18:55:14 +0000 (18:55 +0000)
committermaxcooper <maxcooper>
Mon, 14 Jul 2003 18:55:14 +0000 (18:55 +0000)
src/share/org/securityfilter/authenticator/BasicAuthenticator.java

index 7eb43fe..529dcaa 100644 (file)
@@ -1,7 +1,7 @@
 /*
- * $Header: /cvsroot/securityfilter/securityfilter/src/share/org/securityfilter/authenticator/BasicAuthenticator.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/BasicAuthenticator.java,v 1.2 2003/07/14 18:55:14 maxcooper Exp $
+ * $Revision: 1.2 $
+ * $Date: 2003/07/14 18:55:14 $
  *
  * ====================================================================
  * The SecurityFilter Software License, Version 1.1
@@ -70,18 +70,19 @@ import java.security.Principal;
  *
  * @author Daya Sharma (iamdaya@yahoo.com, billydaya@sbcglobal.net)
  * @author Max Cooper (max@maxcooper.com)
- * @version $Revision: 1.1 $ $Date: 2003/07/07 13:12:56 $
+ * @version $Revision: 1.2 $ $Date: 2003/07/14 18:55:14 $
  */
 public class BasicAuthenticator implements Authenticator {
-   public static final String BASIC_WINDOW_SHOWN = "basic_window_shown";
-   public static final String LOGIN_ATTEMPTS = "loginAttempts";
-   protected static final String DUMMY_TOKEN = "dummyToken";
+   public static final String LOGIN_ATTEMPTS = BasicAuthenticator.class.getName() + ".LOGIN_ATTEMPTS";
 
-   public static final Base64 base64Helper = new Base64();
-
-   protected String tooManyIncorrectLogins;
+   // todo: allow this message to be configured, internationalized, etc.
+   public static final String LOGIN_FAILED_MESSAGE = "Sorry you are having problems logging in, please try again";
+   public static final int MAX_ATTEMPTS = 3;
 
    protected SecurityRealmInterface realm;
+   protected String realmName;
+   protected Base64 base64Helper;
+
 
    /**
     * Initialize this Authenticator.
@@ -91,7 +92,8 @@ public class BasicAuthenticator implements Authenticator {
     */
    public void init(FilterConfig filterConfig, SecurityConfig securityConfig) throws Exception {
       realm = securityConfig.getRealm();
-      tooManyIncorrectLogins = "Sorry you are having problems logging in, please try again";
+      realmName = securityConfig.getRealmName();
+      base64Helper = new Base64();
    }
 
    /**
@@ -113,77 +115,101 @@ public class BasicAuthenticator implements Authenticator {
     * @return true if the filter should return after this method ends, false otherwise
     */
    public boolean processLogin(SecurityRequestWrapper request, HttpServletResponse response) throws Exception {
-      if (basicAuthentication(request)) {
-         request.getSession().removeAttribute(BASIC_WINDOW_SHOWN);
-         String username = parseUsername(request.getHeader("Authorization"));
-         String password = parsePassword(request.getHeader("Authorization"));
-         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.
-            request.setUserPrincipal(principal);
-            String continueToURL = SecurityFilter.getContinueToURL(request);
-            request.getSession().setAttribute(DUMMY_TOKEN, DUMMY_TOKEN);
-            // This is the url that the user was initially accessing before being prompted for login.
-            response.sendRedirect(response.encodeRedirectURL(continueToURL));
-         } else {
-            // login failed
-            // show the basic authentication window again.
-            showLogin(request.getCurrentRequest(), response);
+      if (request.getUserPrincipal() == null) {
+         // attempt to dig out authentication info only if the user has not yet been authenticated
+         String authorizationHeader = request.getHeader("Authorization");
+         HttpSession session = request.getSession();
+         if (authorizationHeader != null && session.getAttribute(LOGIN_ATTEMPTS) != null) {
+            String decoded = decodeBasicAuthorizationString(authorizationHeader);
+            String username = parseUsername(decoded);
+            String password = parsePassword(decoded);
+            Principal principal = realm.authenticate(username, password);
+            if (principal != null) {
+               // login successful
+               request.getSession().removeAttribute(LOGIN_ATTEMPTS);
+               request.setUserPrincipal(principal);
+            } else {
+               // login failed
+               // show the basic authentication window again.
+               showLogin(request.getCurrentRequest(), response);
+               return true;
+            }
          }
       }
       return false;
    }
 
    /**
-    * Returns true if this request includes BASIC auth info.
+    * All requests should be subject to security checking for BASIC authentication.
     *
     * @param request
-    * @return
+    * @return always false -- check all requests
+    */
+   public boolean bypassSecurityForThisRequest(SecurityRequestWrapper request, URLPatternMatcher patternMatcher) {
+      return false;
+   }
+
+   /**
+    * Show the login page.
+    *
+    * @param request the current request
+    * @param response the current response
     */
-   private boolean basicAuthentication(HttpServletRequest request) {
-      return (
-         request.getSession().getAttribute(BASIC_WINDOW_SHOWN) != null
-         && request.getHeader("Authorization") != null
-      );
+   public void showLogin(HttpServletRequest request, HttpServletResponse response) throws IOException {
+      // save this request
+      SecurityFilter.saveRequestInformation(request);
+
+      // determine the number of login attempts
+      int loginAttempts;
+      if (request.getSession().getAttribute(LOGIN_ATTEMPTS) != null) {
+         loginAttempts = ((Integer) request.getSession().getAttribute(LOGIN_ATTEMPTS)).intValue();
+         loginAttempts += 1;
+      } else {
+         loginAttempts = 1;
+      }
+      request.getSession().setAttribute(LOGIN_ATTEMPTS, new Integer(loginAttempts));
+
+      if (loginAttempts <= MAX_ATTEMPTS) {
+         response.setHeader("WWW-Authenticate", "BASIC realm=\"" + realmName + "\"");
+         response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
+      } else {
+         request.getSession().removeAttribute(LOGIN_ATTEMPTS);
+         response.sendError(HttpServletResponse.SC_UNAUTHORIZED, LOGIN_FAILED_MESSAGE);
+      }
    }
 
    /**
     * Parse the username out of the BASIC authorization header string.
-    * @param authorization
-    * @return
+    * @param decoded
+    * @return username parsed out of decoded string
     */
-   private String parseUsername(String authorization) {
-      String unencoded = decodeBasicAuthorizationString(authorization);
-      if (unencoded == null) {
+   private String parseUsername(String decoded) {
+      if (decoded == null) {
          return null;
       } else {
-         int colon = unencoded.indexOf(':');
+         int colon = decoded.indexOf(':');
          if (colon < 0) {
             return null;
          } else {
-            return unencoded.substring(0, colon).trim();
+            return decoded.substring(0, colon).trim();
          }
       }
    }
 
    /**
-    * Parse the password out of the BASIC authorization header string.
-    * @param authorization
-    * @return
+    * Parse the password out of the decoded BASIC authorization header string.
+    * @param decoded
+    * @return password parsed out of decoded string
     */
-   private String parsePassword(String authorization) {
-      String unencoded = decodeBasicAuthorizationString(authorization);
-      if (unencoded == null) {
+   private String parsePassword(String decoded) {
+      if (decoded == null) {
          return null;
       } else {
-         int colon = unencoded.indexOf(':');
+         int colon = decoded.indexOf(':');
          if (colon < 0) {
             return (null);
          } else {
-            return unencoded.substring(colon + 1).trim();
+            return decoded.substring(colon + 1).trim();
          }
       }
    }
@@ -192,7 +218,7 @@ public class BasicAuthenticator implements Authenticator {
     * Decode the BASIC authorization string.
     *
     * @param authorization
-    * @return
+    * @return decoded string
     */
    private String decodeBasicAuthorizationString(String authorization) {
       if (authorization == null || !authorization.toLowerCase().startsWith("basic ")) {
@@ -203,55 +229,6 @@ public class BasicAuthenticator implements Authenticator {
          return new String(base64Helper.decodeBase64(authorization.getBytes()));
       }
    }
-
-   /**
-    * Show the login page.
-    *
-    * @param request the current request
-    * @param response the current response
-    */
-   public void showLogin(HttpServletRequest request, HttpServletResponse response) throws IOException {
-      // save this request
-      SecurityFilter.saveRequestInformation(request);
-
-      // redirect to login page
-      request.getSession().setAttribute(BASIC_WINDOW_SHOWN, "shown");
-      int loginAttempts = 1;
-      if (request.getSession().getAttribute(LOGIN_ATTEMPTS) != null) {
-         loginAttempts = ((Integer) request.getSession().getAttribute(LOGIN_ATTEMPTS)).intValue();
-         loginAttempts += 1;
-      }
-      // todo: we can put some useful message here, perhaps a internationlizable format of message.
-      String loginAttemptMessage = "Login attempt number " + loginAttempts;
-      String logo;
-      if (loginAttempts <= 3) {
-         String realm = String.valueOf(Math.random());
-         if (loginAttempts < 2) {
-            logo = "Basic Auth with Security Filter";
-         } else {
-            logo = loginAttemptMessage;
-         }
-         String blankLine = "                                                                   ";
-         logo = blankLine + blankLine + blankLine + logo + blankLine + blankLine;
-         System.err.println("response.setHeader \"WWW-Authenticate\", \"BASIC realm=\"" + logo + realm + "\"");
-         response.setHeader("WWW-Authenticate", "BASIC realm=\"" + realm + logo + "\"");
-         response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
-         request.getSession().setAttribute(LOGIN_ATTEMPTS, new Integer(loginAttempts));
-      } else {
-         request.getSession().removeAttribute(LOGIN_ATTEMPTS);
-         response.sendError(HttpServletResponse.SC_UNAUTHORIZED, tooManyIncorrectLogins);
-      }
-   }
-
-   /**
-    * All requests should be subject to security checking for BASIC authentication.
-    *
-    * @param request
-    * @return always false -- check all requests
-    */
-   public boolean bypassSecurityForThisRequest(SecurityRequestWrapper request, URLPatternMatcher patternMatcher) {
-      return false;
-   }
 }
 
 // ------------------------------------------------------------------------