SMODL Service Deployment Tutorial

ABSTRACT

This paper describes the runtime engine initialization process and the security limitations that can be applied on service method calls. The role validation mechanism which uses roles to support different user profiles is also discussed.

Understanding the SMODL service

The high-level composition of a SMODL service includes four items. The list below gives the reader a brief overview of each item.

The SMODL service deployment

  1. An initialization of the runtime engine

    An implementor of the ISmodlServerRuntime interface represents the runtime engine. As any other runtime engine, the SMODL engine must be running in order for the SMODL service to execute. There is one-to-one correspondence between a SMODL service and a SMODL runtime engine. This means that if you need to run another SMODL service in the same container/application you need to create and run another runtime.

    ISmodlServerRuntime interface represents the runtime manager which is responsible for runtime initialization. For a successful initialization the following sequence should occur in the application container:

  2. Role validation (optional)

    The latest implementation of the SMODL runtime allows to control execution of SMODL service methods. During its initialization the runtime may get an object implementing the IRoleValidator interface. In this case the runtime checks if a service method can be called before in fact calling it. This is achieved by comparing the list of roles provided by the IRoleValidator and the list of roles assigned to a particular method. If there is an overlap between two sets of roles then the method can be called, otherwise an appropriate exception is thrown. Roles are just arbitrary strings. Since both IRoleValidator object and mapping between roles and methods are provided by the Web application component running the Web service, the execution of the service method is fully controlled by the Web application. To illustrate this we provide an example of the SMODL service implementation supporting role-based execution of methods.

    Let's suppose a SMODL service deployment is implemented by extension of the SmodlHttpServlet. The extension alters the initialization of the SMODL runtime in order to add the mapping between service methods and roles. An implementation of the IRoleValidator interface is also provided.

    securityService = new SessionSecurityService();
    runtime.setRoleValidator(securityService);
    runtime.setRoleMethodMapping(new String[] { "commonMethod" },
                                    new String[] { "anonymous", "user" });
    runtime.setRoleMethodMapping(new String[] { "userMethod" },
                                    new String[] { "user" });
    

    Code for the SessionSecurityService class will be displayed and explained further in the article. The above fragment of the runtime initialization sets mapping between the "commonMethod" method of the service and roles "anonymous" and "user" as well as the mapping between the "userMethod" method of the service and the "user" role. If the "user" role corresponds to an authenticated user of the service and the "anonymous" role corresponds to a non-authenticated user then the "userMethod" method can be only called by authenticated users while the "commonMethod" can be called by any service user. To achieve this we need a glue between roles and user authentication. The SessionSecurityService objects provides this glue.

    public class SessionSecurityService implements ISecurityService, IRoleValidator {
            
            private static ThreadLocal sessionHolder = new ThreadLocal();
    
            public void userAuthenticated(String username) {
                    
                    HttpSession session = sessionHolder.get();
                    session.setAttribute("username", username);                
            }
    
            public boolean isSessionValid() {
                    
                    HttpSession session = sessionHolder.get();
                    Object username = session.getAttribute("username");
                    
                    if (username != null) {
                            return true;
                    }
                    return false;
            }
            
            public static ThreadLocal getSessionHolder() {
                    return sessionHolder;
            }
    
            public String getUsername() {
                    
                    String result = null;
                    HttpSession session = sessionHolder.get();
                    result = (String)session.getAttribute("username");
                    return result;                
            }
    
            public void userLoggedOff() {
                    HttpSession session = sessionHolder.get();
                    session.removeAttribute("username");
            }
            
            public String[] getRoles() {
                    return isSessionValid()? new String[] { "user" } : new String[] { "anonymous" };
            }
            
    }
    

    An instance of this class stores a name of an authenticated user in the username property. This property is kept in the HttpSession object attached to a current thread. The Web application signalizes that the user is authenticated by calling the userAuthenticated() method. If the user logs out the Web application should call the userLoggedOff() method. Following the logic of implementation, the SessionSecurityService object returns role "user" if a user is authenticated and "anonymous" if a user is not authenticated in answer to the getRoles() method call.

    To complete the example the extension of the SmodlHttpServlet should override the doPost method:

    protected void doPost(HttpServletRequest request, HttpServletResponse response)
    			throws ServletException, IOException {
                                                                                    
    SessionSecurityService.getSessionHolder().set(request.getSession());
            super.doPost(request, response);
            SessionSecurityService.getSessionHolder().remove();
            
         }
    }
    

    So in the beginning of each request the extension attaches the session object to the current thread and detaches it once the request was processed.