markt 2005/05/11 14:39:41 Modified: catalina/src/share/org/apache/catalina/authenticator FormAuthenticator.java SavedRequest.java webapps/docs changelog.xml Log: Include request body in saved request when using FORM authentication. - Fixes problem with saved request assuming platform default encoding for POSTed parameters. - Improves restoration of request by using CoyoteRequest Revision Changes Path 1.20 +89 -25 jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/authenticator/FormAuthenticator.java Index: FormAuthenticator.java =================================================================== RCS file: /home/cvs/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/authenticator/FormAuthenticator.java,v retrieving revision 1.19 retrieving revision 1.20 diff -u -r1.19 -r1.20 --- FormAuthenticator.java 31 Mar 2005 10:31:54 -0000 1.19 +++ FormAuthenticator.java 11 May 2005 21:39:41 -0000 1.20 @@ -19,11 +19,11 @@ import java.io.IOException; +import java.io.InputStream; import java.security.Principal; import java.util.Enumeration; import java.util.Iterator; import java.util.Locale; -import java.util.Map; import javax.servlet.RequestDispatcher; import javax.servlet.http.Cookie; @@ -36,11 +36,14 @@ import org.apache.catalina.deploy.LoginConfig; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.coyote.InputBuffer; +import org.apache.coyote.http11.InputFilter; +import org.apache.coyote.http11.InternalInputBuffer; +import org.apache.tomcat.util.buf.ByteChunk; import org.apache.tomcat.util.buf.CharChunk; import org.apache.tomcat.util.buf.MessageBytes; - /** * An <b>Authenticator</b> and <b>Valve</b> implementation of FORM BASED * Authentication, as described in the Servlet API Specification, Version 2.2. @@ -187,7 +190,8 @@ if (matchRequest(request)) { session = request.getSessionInternal(true); if (log.isDebugEnabled()) - log.debug("Restore request from session '" + session.getIdInternal() + log.debug("Restore request from session '" + + session.getIdInternal() + "'"); principal = (Principal) session.getNote(Constants.FORM_PRINCIPAL_NOTE); @@ -273,7 +277,8 @@ session = request.getSessionInternal(false); if (session == null) { if (containerLog.isDebugEnabled()) - containerLog.debug("User took so long to log on the session expired"); + containerLog.debug + ("User took so long to log on the session expired"); response.sendError(HttpServletResponse.SC_REQUEST_TIMEOUT, sm.getString("authenticator.sessionExpired")); return (false); @@ -345,7 +350,8 @@ * @param request The request to be restored * @param session The session containing the saved information */ - protected boolean restoreRequest(Request request, Session session) { + protected boolean restoreRequest(Request request, Session session) + throws IOException { // Retrieve and remove the SavedRequest object from our session SavedRequest saved = (SavedRequest) @@ -361,7 +367,8 @@ while (cookies.hasNext()) { request.addCookie((Cookie) cookies.next()); } - request.clearHeaders(); + + request.getCoyoteRequest().getMimeHeaders().recycle(); Iterator names = saved.getHeaderNames(); while (names.hasNext()) { String name = (String) names.next(); @@ -370,24 +377,39 @@ request.addHeader(name, (String) values.next()); } } + request.clearLocales(); Iterator locales = saved.getLocales(); while (locales.hasNext()) { request.addLocale((Locale) locales.next()); } - request.clearParameters(); + + request.getCoyoteRequest().getParameters().recycle(); + if ("POST".equalsIgnoreCase(saved.getMethod())) { - Iterator paramNames = saved.getParameterNames(); - while (paramNames.hasNext()) { - String paramName = (String) paramNames.next(); - String paramValues[] = - saved.getParameterValues(paramName); - request.addParameter(paramName, paramValues); - } + ByteChunk body = saved.getBody(); + + // Set content length + request.getCoyoteRequest().setContentLength(body.getLength()); + + // Restore body + InputFilter savedBody = new SavedRequestInputFilter(body); + InternalInputBuffer internalBuffer = (InternalInputBuffer) + request.getCoyoteRequest().getInputBuffer(); + internalBuffer.addActiveFilter(savedBody); + + // Set content type + MessageBytes contentType = MessageBytes.newInstance(); + contentType.setString("application/x-www-form-urlencoded"); + request.getCoyoteRequest().setContentType(contentType); } - request.setMethod(saved.getMethod()); - request.setQueryString(saved.getQueryString()); - request.setRequestURI(saved.getRequestURI()); + request.getCoyoteRequest().method().setString(saved.getMethod()); + + request.getCoyoteRequest().queryString().setString + (saved.getQueryString()); + + request.getCoyoteRequest().requestURI().setString + (saved.getRequestURI()); return (true); } @@ -398,8 +420,10 @@ * * @param request The request to be saved * @param session The session to contain the saved information + * @throws IOException */ - private void saveRequest(Request request, Session session) { + private void saveRequest(Request request, Session session) + throws IOException { // Create and populate a SavedRequest object for this request SavedRequest saved = new SavedRequest(); @@ -422,13 +446,22 @@ Locale locale = (Locale) locales.nextElement(); saved.addLocale(locale); } - Map parameters = request.getParameterMap(); - Iterator paramNames = parameters.keySet().iterator(); - while (paramNames.hasNext()) { - String paramName = (String) paramNames.next(); - String paramValues[] = (String[]) parameters.get(paramName); - saved.addParameter(paramName, paramValues); + + if ("POST".equalsIgnoreCase(request.getMethod())) { + // Note that the size of the request body is limited by: + // request.getConnector().getMaxPostSize() + + byte[] buffer = new byte[4096]; + int bytesRead; + InputStream is = request.getInputStream(); + ByteChunk body = new ByteChunk(); + + while ( (bytesRead = is.read(buffer) ) >= 0) { + body.append(buffer, 0, bytesRead); + } + saved.setBody(body); } + saved.setMethod(request.getMethod()); saved.setQueryString(request.getQueryString()); saved.setRequestURI(request.getRequestURI()); @@ -460,5 +493,36 @@ } + protected class SavedRequestInputFilter implements InputFilter { + + protected ByteChunk input = null; + + public SavedRequestInputFilter(ByteChunk input) { + this.input = input; + } + + public int doRead(ByteChunk chunk, org.apache.coyote.Request request) + throws IOException { + return input.substract(chunk); + } + + public void setRequest(org.apache.coyote.Request request) { + } + + public void recycle() { + input = null; + } + + public ByteChunk getEncodingName() { + return null; + } + + public void setBuffer(InputBuffer buffer) { + } + + public long end() throws IOException { + return 0; + } + } } 1.4 +15 -6 jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/authenticator/SavedRequest.java Index: SavedRequest.java =================================================================== RCS file: /home/cvs/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/authenticator/SavedRequest.java,v retrieving revision 1.3 retrieving revision 1.4 diff -u -r1.3 -r1.4 --- SavedRequest.java 27 Feb 2004 14:58:41 -0000 1.3 +++ SavedRequest.java 11 May 2005 21:39:41 -0000 1.4 @@ -25,6 +25,8 @@ import javax.servlet.http.Cookie; +import org.apache.tomcat.util.buf.ByteChunk; + /** * Object that saves the critical information from a request so that @@ -34,11 +36,6 @@ * <b>IMPLEMENTATION NOTE</b> - It is assumed that this object is accessed * only from the context of a single thread, so no synchronization around * internal collection classes is performed. - * <p> - * <b>FIXME</b> - Currently, this object has no mechanism to save or - * restore the data content of the request, although it does save - * request parameters so that a POST transaction can be faithfully - * duplicated. * * @author Craig R. McClanahan * @version $Revision$ $Date$ @@ -167,5 +164,17 @@ this.requestURI = requestURI; } + + /** + * The body of this request. + */ + private ByteChunk body = null; + + public ByteChunk getBody() { + return (this.body); + } + public void setBody(ByteChunk body) { + this.body = body; + } } 1.307 +5 -0 jakarta-tomcat-catalina/webapps/docs/changelog.xml Index: changelog.xml =================================================================== RCS file: /home/cvs/jakarta-tomcat-catalina/webapps/docs/changelog.xml,v retrieving revision 1.306 retrieving revision 1.307 diff -u -r1.306 -r1.307 --- changelog.xml 11 May 2005 21:22:14 -0000 1.306 +++ changelog.xml 11 May 2005 21:39:41 -0000 1.307 @@ -148,6 +148,11 @@ <fix> Fix NPE when POST size exceeds limit defined by maxPostSize. (markt) </fix> + <fix> + Fix FORM authentication so POSTed parameters are not assumed to be encoded with platform + default encoding. A side effect of this fix is that the bodies of POST requests that + require FORM authentication are now buffered and made available after a sucessful login. (markt) + </fix> </changelog> </subsection>
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]