Wednesday, February 11, 2015

How to Handle Http Session Expiration on Login Page



We had a problem where if you sat on the login page for longer than the http session timeout period and then entered your username/password and attempted to login, you would get redirected back to the login page and have to enter it a 2nd time.  This got annoying so to fix this we added code to our custom exception handler to catch the ViewExpiredException.  A custom exception handler will catch all uncaught exceptions and is useful for displaying a generic "Something went wrong" page.    For information on how to set up a custom Exception handler see this blog by Frank Nimphius

The relevant part of the code I added to this exception handler is shown below.  It performs these steps
  • Retrieve username & password from request
  • Log user in
  • redirect to home page
 If the user entered an incorrect username/password then redirecting to home page will actually redirect back to the login page because the home page requires authentication and a valid login to access.
 
if (throwable instanceof ViewExpiredException) {
  ExternalContext extContext = FacesContext.getCurrentInstance().getExternalContext();
  String pathInfo = extContext.getRequestPathInfo();
  if (pathInfo.equals("/login")) {
      String username = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("usernameInput");
      String password = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("passwordInput");
      Login login = new Login();
      String action = login.login(username, password); // login the user even though the http session was expired.
      extContext.redirect(extContext.getRequestContextPath());
      context.responseComplete();
      return;
    }

}

The Login class is our own managed bean that is used by the login page.  It performs a bunch of thing, including creating a login history record among others, but the pertinent thing it does to actually login the user is this line 
                 authSuccess =  ServletAuthentication.login(user, pw, request, response);

 Our login page has a number of hidden fields that also need to be accessed during login and if you need to retrieve extra fields you can retrieve them the same way as shown above for the username and password fields.