|
Recipe 11.1. Securing Actions Using a Base ActionProblemYou need to ensure that users are logged in before they can access certain actions. SolutionCreate a base Action, like the one shown in Example 11-1, which implements the security policy. Example 11-1. Enforcing authentication with a base actionpackage com.oreilly.strutsckbk.ch11; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.apache.struts.action.Action; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; import org.apache.struts.webapp.example.Constants; import org.apache.struts.webapp.example.User; public abstract class SecureAction extends Action { // final so cannot be overridden public final ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { HttpSession session = request.getSession( ); User user = (User) session.getAttribute(Constants.USER_KEY); // send back to the logon page if no user if (user == null) return (mapping.findForward("logon")); return doExecute(mapping, form, request, response, user); } public abstract ActionForward doExecute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response, User user) throws Exception; } Concrete Actions that require this policy extend the base SecureAction, shown in Example 11-2. Example 11-2. SecureAction source codepackage com.oreilly.strutsckbk.ch11; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; import org.apache.struts.webapp.example.User; public class TestSecureAction extends SecureAction { public ActionForward doExecute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response, User user) throws Exception { // do real work here return mapping.findForward("success"); } } DiscussionThe base SecureAction is an abstract class that wraps the execute( ) method with the security policy. In the Solution, the policy is simple. The User object is retrieved from the HttpSession; if this object is not found, then the user must not be logged in; control is forwarded to "logon." Otherwise, the abstract doExecute( ) method is called. In addition to the standard execute( ) arguments, the User object is passed through. Your concrete subclasses then implement doExecute( ) instead of execute( ). Enforcing security through a base SecureAction is an understandable approach. However, this solution requires that every concrete Action must subclass SecureAction. If you are using the DispatchAction or other Struts built-in Actions, you'll need to create your own subclasses for these that perform the security checks. In a team environment, you'll need to ensure all developers abide by these rules. More importantly, the base Action approach only provides security for HTTP requests that go through your base Action. It doesn't provide any security for directly accessed JSPs, static HTML pages, and other resources accessed outside of Struts or through a different Action. If you ensure all requests go through your base Action, then this may not be an issue; however, many applications are not written in such a way. See AlsoThe Base Action technique is discussed in Programming Jakarta Struts by Chuck Cavaness (O'Reilly). The Struts JavaDoc for the Action class can be found at http://struts.apache.org/api/org/apache/struts/action/Action.html. |
|