Newsletter sign-up
View all newsletters

Enterprise Java Newsletter
Stay up to date on the latest tutorials and Java community news posted on JavaWorld

Sponsored Links

Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs

Mix protocols transparently in Struts

Extend Struts to implement a mixed protocol solution for Web applications

  • Print
  • Feedback

Page 3 of 6

SecureActionServlet

In addition to the standard config and mapping initialization parameters, we must specify two new properties: our application's port numbers for the HTTP and HTTPS protocols. We specify these the same way we specify the other initialization parameters. The values we assign to the port number parameters are stored in the two properties we define for our extension to the ActionServlet class.

This new extension, called SecureActionServlet, initializes these new properties. The servlet entry in the web.xml now has the following code:

  <servlet id="Servlet_1">
    <servlet-name>action</servlet-name>
    <servlet-class>org.apache.struts.action.SecureActionServlet</servlet-class>
    <!-- Struts Config -->
    <init-param>
      <param-name>config</param-name>
      <param-value>/WEB-INF/struts-config.xml</param-value>
    </init-param>
    <init-param>
      <param-name>mapping</param-name>
      <param-value>org.apache.struts.action.SecureActionMapping</param-value>
    </init-param>
    <!- other initialization parameters -->
    <init-param>
      <param-name>http-port</param-name>
      <param-value>8080</param-value>
    </init-param>
    <init-param>
      <param-name>https-port</param-name>
      <param-value>8443</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>


Note that we substituted the name of our new SecureActionServlet subclass where ActionServlet was previously specified.

The default values for the port number properties, used in cases where values are not assigned through the initialization parameters, are the standard HTTP and HTTPS port numbers of 80 and 443, respectively. SecureActionServlet implements the logic necessary to determine whether to perform a redirect for channeling an action request to the proper protocol. This logic first finds the SecureActionMapping object for a Struts action. Next, it checks the value of that object's secure property to determine whether it must execute a redirect to the specified protocol for calling the Action subclass's perform() method. All other ActionServlet behavior remains unchanged in its subclass. The full source code for SecureActionServlet appears below:

package org.apache.struts.action;
import org.apache.struts.util.SecureRequestUtils;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
/**
 * An extension of the ActionServlet class to add properties for
 * http and https ports.  Performs logic to determine if
 * requests should be redirected to another (http or https) protocol.
 */
public class SecureActionServlet extends ActionServlet {
    protected String httpPort = "80";
    protected String httpsPort = "443";
    public void init() throws ServletException {
        super.init();
        initPorts();
    }
    /**
     * Initializes the http and http port properties
     * from init parameters specified in the web.xml file.
     * If not found there, default values remain.
     */
    protected void initPorts(){
        String value = getServletConfig().getInitParameter("http-port");
        if( value != null ){
        // Other validation code here.
            httpPort = value;
        }
        value = getServletConfig().getInitParameter("https-port");
        if( value != null ){
        // Other validation code here.
            httpsPort = value;
        }
    }
    public void setHttpsPort( String s ){
        this.httpsPort = s;
    }
    public void setHttpPort( String s ){
        this.httpPort = s;
    }
    public String getHttpsPort( ){
        return this.httpsPort;
    }
    public String getHttpPort( ){
        return this.httpPort;
    }
    /**
     * Checks whether servlet should redirect to another protocol
     * before calling the superclass process method.
     *  @param aRequest is the current request object.
     *  @param aResponse is the current response object.
     *  @throws IOException if an input/output error occurs.
     *  @throws ServletException  if a servlet error occurs.
     */
    protected void process(HttpServletRequest request,
                HttpServletResponse response
            ) throws IOException, ServletException {
        // Identify the path component we will use to select a mapping.
        String path = processPath(request);
        if (path == null) {
            if (debug >= 1)
            log(" No path available for request URI " +
                request.getRequestURI());
            response.sendError(HttpServletResponse.SC_BAD_REQUEST,
                       internal.getMessage("processPath"));
            return;
        }
        // Look up the corresponding mapping.
        SecureActionMapping mapping = (SecureActionMapping)processMapping(path, request);
        if (mapping == null) {
            if (debug >= 1)
            log(" No mapping available for path " + path);
            response.sendError(HttpServletResponse.SC_BAD_REQUEST,
                       internal.getMessage("processInvalid", path));
            return;
        }
        // Redirect to https/http if necessary.
        if( checkSsl(mapping, request, response) ){
            return ;
        }
        super.process(request, response);
    }
    /** Checks to see if SSL should be toggled for this
     *  action.
     *  @param aMapping is the mapping object for this Action.
     *  @param aRequest is the current request object.
     *  @param aResponse is the current response object.
     */
    private boolean checkSsl(SecureActionMapping aMapping,
            HttpServletRequest aRequest,
            HttpServletResponse aResponse){
        String redirectString =
                SecureRequestUtils.getRedirectString(aRequest,
                getHttpPort(),
                getHttpsPort(),
                aMapping.getSecure());
        if( redirectString != null ){
            try{
                // Redirect the page to the desired URL.
                aResponse.sendRedirect(aResponse.encodeRedirectURL( redirectString));
                return true;
            }catch(Exception ioe){
                System.out.println("IOException in redirect" + ioe.getMessage());
            }
        }
        return false;
    }
}


Figure 2 illustrates the class diagram with our new extensions.

  • Print
  • Feedback

Resources