Recipe11.2.Checking for User Login on Any Struts Reques t


Recipe 11.2. Checking for User Login on Any Struts Reques t

Problem

You want to be able to check if a user is logged in for any request made to an action in your struts-config.xml file, but you don't want to have to subclass a custom base Action class.

Solution

Create a custom request processor, overriding the processPreprocess( ) or the processActionPerform( ) method. The custom request processor shown in Example 11-3 retrieves the user object from the HTTP session. If this object is null, an HTTP error response of 403 (Forbidden) is returned.

Example 11-3. Overriding the processPreprocess( ) method
package org.apache.struts.action; import java.io.IOException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.apache.struts.webapp.example.Constants; import org.apache.struts.webapp.example.User; public class CustomRequestProcessor1 extends RequestProcessor {     protected boolean processPreprocess(HttpServletRequest request,             HttpServletResponse response) {         HttpSession session = request.getSession( );         User user = (User) session.getAttribute(Constants.USER_KEY);         if (user == null) {             try {                 response.sendError(403, "User not logged in");             } catch (IOException e) {                 log.error("Unable to send response");             }             return false;         }                  return true;     } }

If you need to use the Struts objects passed to an Action's execute() method, such as the ActionForm and ActionMapping, override the processActionPerform( ) method as shown in Example 11-4. In this example, if the user object is null, control is forwarded to the logon Struts forward; otherwise, the base RequestProcessor.processActionPerform() method is called to continue normal processing.

Example 11-4. Overriding the processActionPerform( ) method
package org.apache.struts.action; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.apache.struts.webapp.example.Constants; import org.apache.struts.webapp.example.User; public class CustomRequestProcessor2 extends RequestProcessor {     protected ActionForward processActionPerform(HttpServletRequest request,             HttpServletResponse response, Action action, ActionForm form,             ActionMapping mapping) throws IOException, ServletException {         HttpSession session = request.getSession( );         User user = (User) session.getAttribute(Constants.USER_KEY);         if (user == null) {             return mapping.findForward("logon");         } else {             return super.processActionPerform(request, response, action, form,                     mapping);                     }     } }

You deploy the custom request processor using the controller element in the struts-config.xml file:

<controller type="com.oreilly.strutsckbk.ch11.CustomRequestProcessor1" />

Discussion

The Solutions shown in this recipe allow you to enforce a security policy across any requests handled by Struts without having to create and extend a special base Action. The first approach (Example 11-3) overrides the processPreprocess( ) method of the Struts RequestProcessor. This method is a general-purpose preprocessing method. The implementation in the base RequestProcessor is a no-op. You return TRue from this method to continue normal processing. If you return false, the RequestProcessor assumes that the response has been written and it aborts normal processing. In Example 11-3, the method checks for a user object in the session. If one is found, the method returns true; otherwise, the method sends the HTTP error code of 403 (Forbidden).

The second approach overrides the processActionPerform( ) method. Like the first approach, the user object is retrieved from the HTTP session. Unlike the first approach, however, Struts API objects are available. If the user object isn't found, you call the findForward() method on the ActionMapping to forward to "logon." Otherwise, you call the super.processActionPerform( ) method where the base RequestProcessor calls action.execute( ) and handles any thrown exception:

protected ActionForward processActionPerform(HttpServletRequest request,                          HttpServletResponse response,                          Action action,                          ActionForm form,                          ActionMapping mapping)         throws IOException, ServletException {     try {          return (action.execute(mapping, form, request, response));     } catch (Exception e) {         return (processException(request, response,                                  e, form, mapping));     } }

The two approaches shown here apply the security policy to all Actions. If needed, you can customize the Solution so the login check is selectively applied. In the first approach, which overrides processPreprocess( ), you could look for a special request parameter or attribute that indicates if the login check is required. In the second approach, you could employ a custom ActionMapping containing a property indicating if the action was secured or not.

Some Struts applications require a custom RequestProcessor. Tiles applications, for example, use the TilesRequestProcessor. To implement this Solution, you'll need to extend the custom RequestProcessor currently used instead of the base Struts RequestProcessor.


See Also

Like using a base Action, directly accessed JSPs and static HTML pages aren't secured by the Solution. These resources can be selectively secured using a custom JSP tag as shown in Recipe 11.3.

The Struts RequestProcessor also processes roles. You can override the processRoles() method to achieve custom handling, as shown in Recipe 11-4. You can learn about additional RequestProcessor methods in the Struts User's Guide "Controller" section at http://struts.apache.org/userGuide/building_controller.html.

Custom action mappings are discussed in Recipe 2.8.



    Jakarta Struts Cookbook
    Jakarta Struts Cookbook
    ISBN: 059600771X
    EAN: 2147483647
    Year: 2005
    Pages: 200

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net