Recipe11.8.Limiting Access for Specific URLs by Role


Recipe 11.8. Limiting Access for Specific URLs by Role

Problem

You need to verify the user is authorized to access selected URLs based on the user's security role and profile.

Solution

Use a servlet filter such as the one shown in Example 11-14.

Example 11-14. Authorization filter
package com.oreilly.strutsckbk.ch11.ams; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.apache.struts.Globals; import org.apache.struts.action.ActionErrors; import org.apache.struts.action.ActionMessage; public class AuthorizationFilter implements Filter {     public void init(FilterConfig filterConfig) throws ServletException {         String roles = filterConfig.getInitParameter("roles");         if (roles == null || "".equals(roles)) {             roleNames = new String[0];         } else {             roles.trim( );            // use the new split method of JDK 1.4             roleNames = roles.split("\\s*,\\s*");         }         onFailure = filterConfig.getInitParameter("onFailure");         if (onFailure == null || "".equals(onFailure)) {             onFailure = "/index.jsp";         }     }     public void doFilter(ServletRequest request, ServletResponse response,             FilterChain chain) throws IOException, ServletException {         HttpServletRequest req = (HttpServletRequest) request;         HttpServletResponse res = (HttpServletResponse) response;         HttpSession session = req.getSession( );         User user = (User) session.getAttribute("user");         ActionErrors errors = new ActionErrors( );         if (user != null) {             boolean hasRole = false;             for (int i = 0; i < roleNames.length; i++) {                 if (user.hasRole(roleNames[i])) {                     hasRole = true;                     break;                 }             }             if (!hasRole) {                 errors.add(ActionErrors.GLOBAL_MESSAGE, new ActionMessage(                         "error.authorization.required"));             }         }         if (errors.isEmpty( )) {             chain.doFilter(request, response);         } else {             req.setAttribute(Globals.ERROR_KEY, errors);             req.getRequestDispatcher(onFailure).forward(req, res);         }     }     public void destroy( ) {     }     private String[] roleNames;     private String onFailure; }

Discussion

Servlet filters, introduced as part of the Servlet 2.3 specification, provide for custom request and response processing that can be applied across any (and all) web resources. Filters can alter a request before it arrives at its destination and, likewise, can modify the response after it leaves a destination. Filters can be applied to static HTML pages, JSP pages, Struts actions, essentially any resource that you can specify with a URL.

You can use a filter to prohibit or allow access to resources based on any user information. Container-managed security (Recipe 11.9) provides a limited form of this capability, known as role-based access control. With a filter, you can implement role-based access control or any other security policy desired. The Solution shows an example usage that implements custom role-based authorization. This filter performs a similar security check as the custom RoleRequestProcessor of Example 11-14.

Initialization parameters specify the required roles and the page to forward to if the authorization check fails. For each combination of roles and mapped URLs, you can deploy a separate instance of the filter class. Each instance, specified by the filter element, can have its own set of initialization parameters and filter mappings. Example 11-15, taken from the web.xml file, shows a deployment that uses two instances of the same authorization filter.

Example 11-15. Deploying two instances of the authorization filter (partial)
<filter>     <filter-name>adminAuthFilter</filter-name>     <filter-class>         com.oreilly.strutsckbk.ch11.ams.AuthorizationFilter     </filter-class>     <init-param>         <param-name>roles</param-name>         <param-value>admin</param-value>     </init-param>     <init-param>         <param-name>onFailure</param-name>         <param-value>/index.jsp</param-value>     </init-param> </filter> <filter>     <filter-name>managerAuthFilter</filter-name>     <filter-class>         com.oreilly.strutsckbk.ch11.ams.AuthorizationFilter     </filter-class>     <init-param>         <param-name>roles</param-name>         <param-value>manager,asstManager</param-value>     </init-param>     <init-param>         <param-name>onFailure</param-name>         <param-value>/index.jsp</param-value>     </init-param> </filter> <filter-mapping>     <filter-name>adminAuthFilter</filter-name>     <url-pattern>/admin/*</url-pattern> </filter-mapping> <filter-mapping>     <filter-name> managerAuthFilter </filter-name>     <url-pattern>/mgr/*</url-pattern> </filter-mapping> <filter-mapping>     <filter-name> managerAuthFilter </filter-name>     <url-pattern>/usr/*</url-pattern> </filter-mapping>

Unlike other filters in this chapter, the authorization filter of Example 11-14 truly integrates with Struts. If a user doesn't have a required role, then a set of ActionErrors are created and stored as a request attribute. Though the filter only has access to the request and response, it integrates with Struts based on knowing how Struts stores the ActionErrors in the request. Unlike Actions, filters don't have access to Struts helper methods for accessing objects, like ActionErrors, that may be stored in the servlet request or session. To get around this, you can retrieve Struts objects. By using the constants defined in the org.apache.struts.Globals class, you can protect your code from future changes to Struts internals.

See Also

For a complete application-managed security solution, you will want to implement an authentication mechanism. Recipe 11.6 presents a servlet filter that can be used for this purpose. To enforce authentication prior to authorization, list the authentication filter before the authorization filter in the filter-mapping declarations.

Recipe 11.10 shows how to use the open source SecurityFilter software for providing similar functionality as the filter presented in this recipe.

Java Servlet Programming by Jason Hunter (O'Reilly) covers servlet filters in-depth. Sun's Java site has a good article on the essentials of servlet filters. It can be found at http://java.sun.com/products/servlet/Filters.html.



    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