Recipe11.4.Restricting Actions by Role


Recipe 11.4. Restricting Actions by Role

Problem

You want to allow a user to access an action if that user has a specific role.

Solution

Use the roles attribute of the action element to specify the roles that are permitted to use the action:

<!-- Display all users --> <action    path="/ViewUsers"         forward="/view_users.jsp"           roles="manager,sysadmin" />

Discussion

Struts actions, configured via the action element in the struts-config.xml file, can be restricted to certain roles using the roles attribute. This attribute accepts a comma-separated list of role names. When a request is received for the action, the RequestProcessor.processRoles( ) method checks that the user has at least one of the roles specified. If the user doesn't have one of the roles, the HTTP 403 error (Forbidden) is sent; otherwise, processing continues normally. Here is the processRoles( ) method from the Struts RequestProcessor:

protected boolean processRoles( HttpServletRequest request,                                 HttpServletResponse response,                                 ActionMapping mapping )         throws IOException, ServletException {     // Is this action protected by role requirements?     String roles[] = mapping.getRoleNames( );     if ((roles == null) || (roles.length < 1)) {         return (true);     }     // Check the current user against the list of required roles     for (int i = 0; i < roles.length; i++) {         if ( request.isUserInRole(roles[i]) ) {             if (log.isDebugEnabled( )) {                 log.debug(" User '" + request.getRemoteUser( ) +                     "' has role '" + roles[i] + "', granting access");             }             return (true);         }     }     // The current user is not authorized for this action     if (log.isDebugEnabled( )) {         log.debug(" User '" + request.getRemoteUser( ) +             "' does not have any required role, denying access");     }     response.sendError(         HttpServletResponse.SC_FORBIDDEN,         getInternal( ).getMessage("notAuthorized", mapping.getPath( )));     return (false); }

The Struts RequestProcessor determines if a user has a role using the HttpServletRequest.isUserInRole( ) method. This method can only be used if you are using container-managed security (or if you use a Solution such as the one in Recipe 11.10). For application-managed security, you can create your own custom RequestProcessor that overrides the processRoles method.

In Example 11-7, the processRoles( ) method retrieves a User object from the HTTP session. Then, the hasRole( ) method is called on this object to determine if the user has at least one of the required roles.

Example 11-7. Custom role-handling RequestProcessor
package com.oreilly.strutsckbk.ch11; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.*; import org.apache.struts.action.*; import org.apache.struts.webapp.example.User; public class RoleRequestProcessor extends RequestProcessor {     protected boolean processRoles( HttpServletRequest request,                                     HttpServletResponse response,                                      ActionMapping mapping )         throws IOException, ServletException     {         // Is this action protected by role requirements? If not, return true.         String roles[] = mapping.getRoleNames( );         if ((roles == null) || (roles.length < 1)) {             return true;         }         // Check the current user against the list of required roles         HttpSession session = request.getSession( );         User user = (User) session.getAttribute("user");         if (user == null) {             return false;         }         for (int i = 0; i < roles.length; i++) {             if (user.hasRole(roles[i])) {                 return (true);             }         }         // The user does not have one of the roles; send an error         response.sendError( HttpServletResponse.SC_BAD_REQUEST,                             getInternal( ).getMessage("notAuthorized",                             mapping.getPath( )));         return (false);     } }

This custom request processor is deployed using the controller element in the struts-config.xml file:

<controller processor/>

The customization, shown in Example 11-7, used to code the processRoles( ) method to perform checks can be as complex as you want. You have complete access to the servlet request and response, servlet context, HTTP session, and the ActionMapping.

Since container-managed security typically supports a simple flat role structure, using application-managed security along with a custom request processor allows you to handle more complex hierarchical schemes. Because you have access to the servlet response, you can redirect a user to a different URL if that user doesn't pass the security test.


See Also

You can learn about additional RequestProcessor methods in the Struts User's Guide "Controller" section at http://struts.apache.org/userGuide/building_controller.html.

If you want to implement container-managed security for your application, see Recipe 11.9.



    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