Implement request.authenticate()
authormarkt <markt@13f79535-47bb-0310-9956-ffa450edef68>
Tue, 17 Nov 2009 02:19:49 +0000 (02:19 +0000)
committermarkt <markt@13f79535-47bb-0310-9956-ffa450edef68>
Tue, 17 Nov 2009 02:19:49 +0000 (02:19 +0000)
This required re-factoring the Authenticator interface to use HttpServletResponse. It would be nice to refactor to use HttpServletRequest as well but at the moment the authenticator requires too much access to the request internals.

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

java/org/apache/catalina/Authenticator.java
java/org/apache/catalina/authenticator/AuthenticatorBase.java
java/org/apache/catalina/authenticator/BasicAuthenticator.java
java/org/apache/catalina/authenticator/DigestAuthenticator.java
java/org/apache/catalina/authenticator/FormAuthenticator.java
java/org/apache/catalina/authenticator/NonLoginAuthenticator.java
java/org/apache/catalina/authenticator/SSLAuthenticator.java
java/org/apache/catalina/connector/Request.java

index e681996..d44288f 100644 (file)
@@ -21,6 +21,8 @@ package org.apache.catalina;
 import java.io.IOException;
 import java.security.Principal;
 
+import javax.servlet.http.HttpServletResponse;
+
 import org.apache.catalina.connector.Request;
 import org.apache.catalina.connector.Response;
 import org.apache.catalina.deploy.LoginConfig;
@@ -43,13 +45,13 @@ public interface Authenticator {
      * created a response challenge already.
      *
      * @param request Request we are processing
-     * @param response Response we are creating
+     * @param response Response we are populating
      * @param config    Login configuration describing how authentication
      *              should be performed
      *
      * @exception IOException if an input/output error occurs
      */
-    public boolean authenticate(Request request, Response response,
+    public boolean authenticate(Request request, HttpServletResponse response,
             LoginConfig config) throws IOException;
     
     /**
@@ -60,13 +62,13 @@ public interface Authenticator {
      * SSO sessions.
      *
      * @param request The servlet request we are processing
-     * @param response The servlet response we are generating
+     * @param response The servlet response we are populating
      * @param principal The authenticated Principal to be registered
      * @param authType The authentication type to be registered
      * @param username Username used to authenticate (if any)
      * @param password Password used to authenticate (if any)
      */
-    public void register(Request request, Response response,
+    public void register(Request request, HttpServletResponse response,
             Principal principal, String authType,
             String username, String password);
 }
index 4221069..8af48ae 100644 (file)
@@ -30,6 +30,7 @@ import java.util.Random;
 
 import javax.servlet.ServletException;
 import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletResponse;
 
 import org.apache.catalina.Authenticator;
 import org.apache.catalina.Container;
@@ -101,6 +102,10 @@ public abstract class AuthenticatorBase
      */
     protected static final int SESSION_ID_BYTES = 16;
 
+    /**
+     * Authentication header
+     */
+    protected static final String AUTH_HEADER_NAME = "WWW-Authenticate";
 
     /**
      * The message digest algorithm to be used when generating session
@@ -564,14 +569,14 @@ public abstract class AuthenticatorBase
      * created a response challenge already.
      *
      * @param request Request we are processing
-     * @param response Response we are creating
+     * @param response Response we are populating
      * @param config    Login configuration describing how authentication
      *              should be performed
      *
      * @exception IOException if an input/output error occurs
      */
     public abstract boolean authenticate(Request request,
-                                            Response response,
+                                            HttpServletResponse response,
                                             LoginConfig config)
         throws IOException;
 
@@ -708,7 +713,7 @@ public abstract class AuthenticatorBase
      * @param username Username used to authenticate (if any)
      * @param password Password used to authenticate (if any)
      */
-    public void register(Request request, Response response,
+    public void register(Request request, HttpServletResponse response,
                             Principal principal, String authType,
                             String username, String password) {
 
index b14032d..2e07d47 100644 (file)
@@ -25,7 +25,6 @@ import java.security.Principal;
 import javax.servlet.http.HttpServletResponse;
 
 import org.apache.catalina.connector.Request;
-import org.apache.catalina.connector.Response;
 import org.apache.catalina.deploy.LoginConfig;
 import org.apache.catalina.util.Base64;
 import org.apache.juli.logging.Log;
@@ -49,31 +48,6 @@ public class BasicAuthenticator
     extends AuthenticatorBase {
     private static final Log log = LogFactory.getLog(BasicAuthenticator.class);
 
-
-
-    /**
-     * Authenticate bytes.
-     */
-    public static final byte[] AUTHENTICATE_BYTES = {
-        (byte) 'W',
-        (byte) 'W',
-        (byte) 'W',
-        (byte) '-',
-        (byte) 'A',
-        (byte) 'u',
-        (byte) 't',
-        (byte) 'h',
-        (byte) 'e',
-        (byte) 'n',
-        (byte) 't',
-        (byte) 'i',
-        (byte) 'c',
-        (byte) 'a',
-        (byte) 't',
-        (byte) 'e'
-    };
-
-
    // ----------------------------------------------------- Instance Variables
 
 
@@ -116,7 +90,7 @@ public class BasicAuthenticator
      */
     @Override
     public boolean authenticate(Request request,
-                                Response response,
+                                HttpServletResponse response,
                                 LoginConfig config)
         throws IOException {
 
@@ -188,24 +162,18 @@ public class BasicAuthenticator
             }
         }
         
-
-        // Send an "unauthorized" response and an appropriate challenge
-        MessageBytes authenticate = 
-            response.getCoyoteResponse().getMimeHeaders()
-            .addValue(AUTHENTICATE_BYTES, 0, AUTHENTICATE_BYTES.length);
-        CharChunk authenticateCC = authenticate.getCharChunk();
-        authenticateCC.append("Basic realm=\"");
+        StringBuilder value = new StringBuilder(16);
+        value.append("Basic realm=\"");
         if (config.getRealmName() == null) {
-            authenticateCC.append(request.getServerName());
-            authenticateCC.append(':');
-            authenticateCC.append(Integer.toString(request.getServerPort()));
+            value.append(request.getServerName());
+            value.append(':');
+            value.append(Integer.toString(request.getServerPort()));
         } else {
-            authenticateCC.append(config.getRealmName());
+            value.append(config.getRealmName());
         }
-        authenticateCC.append('\"');        
-        authenticate.toChars();
+        value.append('\"');        
+        response.setHeader(AUTH_HEADER_NAME, value.toString());
         response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
-        //response.flushBuffer();
         return (false);
 
     }
index bef80fe..7714378 100644 (file)
@@ -25,12 +25,12 @@ import java.security.NoSuchAlgorithmException;
 import java.security.Principal;
 import java.util.StringTokenizer;
 
+import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
 
 import org.apache.catalina.Realm;
 import org.apache.catalina.connector.Request;
-import org.apache.catalina.connector.Response;
 import org.apache.catalina.deploy.LoginConfig;
 import org.apache.catalina.util.MD5Encoder;
 import org.apache.juli.logging.Log;
@@ -129,7 +129,7 @@ public class DigestAuthenticator
      */
     @Override
     public boolean authenticate(Request request,
-                                Response response,
+                                HttpServletResponse response,
                                 LoginConfig config)
         throws IOException {
 
@@ -400,8 +400,8 @@ public class DigestAuthenticator
      *              should be performed
      * @param nOnce nonce token
      */
-    protected void setAuthenticateHeader(Request request,
-                                         Response response,
+    protected void setAuthenticateHeader(HttpServletRequest request,
+                                         HttpServletResponse response,
                                          LoginConfig config,
                                          String nOnce) {
 
@@ -419,7 +419,7 @@ public class DigestAuthenticator
         String authenticateHeader = "Digest realm=\"" + realmName + "\", "
             +  "qop=\"auth\", nonce=\"" + nOnce + "\", " + "opaque=\""
             + md5Encoder.encode(buffer) + "\"";
-        response.setHeader("WWW-Authenticate", authenticateHeader);
+        response.setHeader(AUTH_HEADER_NAME, authenticateHeader);
 
     }
 
index 46310ed..620954e 100644 (file)
@@ -123,7 +123,7 @@ public class FormAuthenticator
      */
     @Override
     public boolean authenticate(Request request,
-                                Response response,
+                                HttpServletResponse response,
                                 LoginConfig config)
         throws IOException {
 
@@ -305,17 +305,17 @@ public class FormAuthenticator
      * Called to forward to the login page
      * 
      * @param request Request we are processing
-     * @param response Response we are creating
+     * @param response Response we are populating
      * @param config    Login configuration describing how authentication
      *              should be performed
      */
-    protected void forwardToLoginPage(Request request, Response response, LoginConfig config) {
+    protected void forwardToLoginPage(Request request,
+            HttpServletResponse response, LoginConfig config) {
         RequestDispatcher disp =
             context.getServletContext().getRequestDispatcher
             (config.getLoginPage());
         try {
-            disp.forward(request.getRequest(), response.getResponse());
-            response.finishResponse();
+            disp.forward(request.getRequest(), response);
         } catch (Throwable t) {
             log.warn("Unexpected error forwarding to login page", t);
         }
@@ -326,16 +326,17 @@ public class FormAuthenticator
      * Called to forward to the error page
      * 
      * @param request Request we are processing
-     * @param response Response we are creating
+     * @param response Response we are populating
      * @param config    Login configuration describing how authentication
      *              should be performed
      */
-    protected void forwardToErrorPage(Request request, Response response, LoginConfig config) {
+    protected void forwardToErrorPage(Request request,
+            HttpServletResponse response, LoginConfig config) {
         RequestDispatcher disp =
             context.getServletContext().getRequestDispatcher
             (config.getErrorPage());
         try {
-            disp.forward(request.getRequest(), response.getResponse());
+            disp.forward(request.getRequest(), response);
         } catch (Throwable t) {
             log.warn("Unexpected error forwarding to error page", t);
         }
index d89f144..749a38a 100644 (file)
@@ -21,8 +21,9 @@ package org.apache.catalina.authenticator;
 
 import java.io.IOException;
 
+import javax.servlet.http.HttpServletResponse;
+
 import org.apache.catalina.connector.Request;
-import org.apache.catalina.connector.Response;
 import org.apache.catalina.deploy.LoginConfig;
 
 
@@ -73,7 +74,7 @@ public final class NonLoginAuthenticator
      * created a response challenge already.
      *
      * @param request Request we are processing
-     * @param response Response we are creating
+     * @param response Response we are populating
      * @param config    Login configuration describing how authentication
      *              should be performed
      *
@@ -81,7 +82,7 @@ public final class NonLoginAuthenticator
      */
     @Override
     public boolean authenticate(Request request,
-                                Response response,
+                                HttpServletResponse response,
                                 LoginConfig config)
         throws IOException {
 
index 1a3c7e9..e696f4f 100644 (file)
@@ -29,7 +29,6 @@ import org.apache.coyote.ActionCode;
 import org.apache.catalina.Globals;
 import org.apache.catalina.LifecycleException;
 import org.apache.catalina.connector.Request;
-import org.apache.catalina.connector.Response;
 import org.apache.catalina.deploy.LoginConfig;
 
 
@@ -84,7 +83,7 @@ public class SSLAuthenticator
      */
     @Override
     public boolean authenticate(Request request,
-                                Response response,
+                                HttpServletResponse response,
                                 LoginConfig config)
         throws IOException {
 
index efdf4b7..29d9c74 100644 (file)
@@ -54,7 +54,6 @@ import javax.servlet.http.HttpServletResponse;
 import javax.servlet.http.HttpSession;
 import javax.servlet.http.Part;
 
-import org.apache.catalina.Authenticator;
 import org.apache.catalina.Context;
 import org.apache.catalina.Globals;
 import org.apache.catalina.Host;
@@ -2322,8 +2321,13 @@ public class Request
                     sm.getString("coyoteRequest.authenticate.ise"));
         }
 
-        // TODO SERVLET3
-        return false;
+        LoginConfig config = context.getLoginConfig();
+        
+        if (config == null) {
+            throw new ServletException(
+                    sm.getString("coyoteRequest.noLoginConfig"));
+        }
+        return context.getAuthenticator().authenticate(this, response, config);
     }
     
     /**
@@ -2341,12 +2345,13 @@ public class Request
                     sm.getString("coyoteRequest.alreadyAuthenticated"));
         }
         
-        if (context.getLoginConfig() == null) {
+        LoginConfig config = context.getLoginConfig();
+        if (config == null) {
             throw new ServletException(
                     sm.getString("coyoteRequest.noLoginConfig"));
         }
         
-        String authMethod = context.getLoginConfig().getAuthMethod();
+        String authMethod = config.getAuthMethod();
         if (BASIC_AUTH.equals(authMethod) || FORM_AUTH.equals(authMethod) ||
                 DIGEST_AUTH.equals(authMethod)) {
             // Methods support user name and password authentication