JSF, J2EE Container Based Security and Handling Session Timeouts

        I have an application that uses the MVC approach and Oracle’s ADF.  The model and web portion of the application share a session to maintain user data and positions in the tables.  We had a problem of when the users session was timed out (set to an hour in the model and web.xml),  the J2EE Container would automatically take over and re-authenicate the user and take them back to their page. However, our application has custom code that runs when the users come through the index.jsp page that sets a view things and determines what their home page is.  Because the data-model is reset when a session times out and the page would not be in sync with the data model, causing data corruption in our system.

I searched the oracle forums looking for an answer to this problem and thought I had found the solution in this article :

http://thepeninsulasedge.com/frank_nimphius/2007/08/22/adf-faces-detecting-and-handling-user-session-expiry/

Now Frank is a guru when it comes to Jdeveloper and his solution will work for non container based applications, I confirmed this through the forums with a dialog with frank.  He also stated that the J2EE container automatically steps in and can’t be over written.  

So here I have this great solution, from frank, which is to add a custom page controller to the web.xml that compares the requested session to the curent session and redirect if they don’t match. Of course with the container stepping in, they always matched and always rendered the page.  I needed a way to set a custom session variable upon valid login and then have my page controller check it.  

Solution found, or so I thought!   The controller would go before my custom code to set the session variable, so no pages would ever render.  The solution, allow some pages to bypass the custom controller.  There might be a way to do this in the web.xml, but I found it easier to implement in code so here is what I did.

1.  First read Frank’s Article to get a better idea how all this is supposed to work.

2.  Open your web.xml file and add the following code.  Your Filter and mapping will go at the end of the existing filters and mappings.
 <filter>
        <filter-name>ApplicationSessionExpiryFilter</filter-name>
        <filter-class>

            lmit.wots.controller.custom.pagecontroller.ApplicationSessionExpiryFilter

        </filter-class>
        <init-param>
            <param-name>SessionTimeoutRedirect</param-name>
            <param-value>index.jspx</param-value>
        </init-param>
 </filter>

Make sure to use the correct path of where you create your custom classes.

  <filter-mapping>
        <filter-name>ApplicationSessionExpiryFilter</filter-name>
        <servlet-name>Faces Servlet</servlet-name>
 </filter-mapping

3.  Change the code from Franks Solution to:
   
public void doFilter(ServletRequest request, 
            ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
 
boolean bypass = false;
String URL = ((HttpServletRequest)request).getRequestURL().toString();

//These are the two pages that I have allowed to be bypassed
if (URL.contains(”index.jspx”) || URL.contains(”invalidSession.jsp”) )
{
  bypass = true;
}
String data = new String();
try
{
 HttpServletRequest httpRequest = (HttpServletRequest)request;
 HttpSession session = httpRequest.getSession();
 data = session.getAttribute(”logged”) + “”;
}
catch (Exception e)
{
 e.printStackTrace();
}
// VALID is what is set as a session variable when the user

// comes in through the front door.

if (data.compareTo(”VALID”) ==0 || bypass)
{
  chain.doFilter(request, response);
}
else
{
 ((HttpServletResponse) response).sendRedirect(_filterConfig.getInitParameter (”SessionTimeoutRedirect”));
}
}
}

4. Change the redirect page to your main page or a error page telling the user they timed out.  I set mine back to my index page so the user is forced through the front door again and everything is set up again.

5.  In your main page that your users come, or if you have default code that runs for a user on the presentation layer, add code to set the session variable, here is mine:

This is my index.java code that is linked to my JSPX page.
public void beforePhase(PagePhaseEvent event)
{
super.beforePhase(event);
   FacesContext fctx = FacesContext.getCurrentInstance();
   try
   {
    HttpSession session = (HttpSession) fctx.getExternalContext().getSession(false);
      session.setAttribute(”logged”, “VALID”);
   }
   catch (Exception e)
   {
   e.printStackTrace();
   }
  }

The only downside to this method is the fact that the user will have to re-navigate to their work location again since I force them back through the front door, however this a small inconvenience in order to ensure data integrity.

One Response to “JSF, J2EE Container Based Security and Handling Session Timeouts”

  1. Endyamon says:

    I think implementing HttpSessionListener would be a better approach.

Leave a Reply