Close

Servlet - Redirect to login page on session timeout

[Last Updated: Jun 27, 2018]

Following example shows how page is forwarded to login page on session expiration.

We are going to use form based programmatic security by using HttpServletRequest.login() and HttpServletRequest.logout() methods.

We are reusing our programmatic security example. In fact we don't have to do anything special when session expires. The method HttpServletRequest#isUserInRole() will start returning false after session has expired.

Example

Servlet implementing form based security

@WebServlet(name = "securedServlet", urlPatterns = {"/"})
public class MySecuredServlet extends HttpServlet {
  @Override
  protected void doGet(HttpServletRequest req,
                       HttpServletResponse resp) throws ServletException, IOException {

      Principal principal = req.getUserPrincipal();
      if (principal == null || !req.isUserInRole("employee")) {
          LoginHandlerServlet.forwardToLogin(req, resp, null);
          return;
      }
      resp.setContentType("text/html");
      PrintWriter writer = resp.getWriter();
      writer.println("Welcome to the secured page!");
      writer.printf("<br/>User: " + req.getRemoteUser());
      writer.printf("<br/>time: " + LocalDateTime.now());
      writer.println("<br/><a href='/logout'>Logout</a>");
  }

  @Override
  protected void doPost(HttpServletRequest req, HttpServletResponse resp)
          throws ServletException, IOException {
      doGet(req, resp);
  }
}
@WebServlet(name = "loginServlet", urlPatterns = {"/loginHandler"})
public class LoginHandlerServlet extends HttpServlet {
  @Override
  protected void doPost(HttpServletRequest req, HttpServletResponse resp)
          throws ServletException, IOException {

      String theUser = req.getParameter("theUser");
      String thePassword = req.getParameter("thePassword");
      try {
          req.login(theUser, thePassword);
      } catch (ServletException e) {
          System.out.println(e.getMessage());
          forwardToLogin(req, resp, "Error: " + e.getMessage());
          return;
      }
      boolean loggedIn = req.getUserPrincipal() != null && req.isUserInRole("employee");
      if (loggedIn) {
          resp.sendRedirect("/");
      } else {
          forwardToLogin(req, resp, "Login failed.");
      }
  }

  public static void forwardToLogin(HttpServletRequest req, HttpServletResponse resp,
                                    String errorMessage)
          throws ServletException, IOException {

      req.setAttribute("errorMsg", errorMessage);
      req.getRequestDispatcher("/login.jsp")
         .forward(req, resp);
  }
}
@WebServlet(name = "logoutServlet", urlPatterns = {"/logout"})
public class LogoutServlet extends HttpServlet {
  @Override
  protected void doGet(HttpServletRequest req, HttpServletResponse resp)
          throws ServletException, IOException {
      req.logout();
      Principal principal = req.getUserPrincipal();
      if (principal != null) {
          throw new RuntimeException("Cannot log out the user");
      }
      resp.sendRedirect("/");
  }
}

Implementing HttpSessionListener

We are implementing HttpSessionListener to set a custom session timeout value and printing messages to know when session expires.

@WebListener
public class MySessionListener implements HttpSessionListener {
  @Override
  public void sessionCreated(HttpSessionEvent se) {
      System.out.println("-- HttpSessionListener#sessionCreated invoked --");
      HttpSession session = se.getSession();
      System.out.println("session id: " + session.getId());
      session.setMaxInactiveInterval(60);//in seconds
  }

  @Override
  public void sessionDestroyed(HttpSessionEvent se) {
      System.out.println("-- HttpSessionListener#sessionDestroyed invoked --");
  }
}

JSP page

src/main/webapp/login.jsp

<html>
<body>
<div style="color:red">
    <%
     Object msg = request.getAttribute("errorMsg");
        if(msg != null ){
           out.println(msg);
        }
     %>
</div>
<form action="/loginHandler" method="post">
    <table>
        <tr>
            <td> User:</td>
            <td><input type="text" name="theUser"/></td>
        </tr>
        <tr>
            <td> Password:</td>
            <td><input type="password" name="thePassword"/></td>
        </tr>
    </table>
    <input type="submit" value="Submit"/>
</form>
</body>
</html>

Adding tomcat-users.xml

src/main/webapp/config/tomcat-users.xml

<?xml version="1.0" encoding="UTF-8"?>
<tomcat-users>
    <role rolename="employee"/>
    <user username="joe" password="123" roles="employee"/>
</tomcat-users>

Specifying tomcat-user.xml location in pom.xml:

<plugin>
  <groupId>org.apache.tomcat.maven</groupId>
  <artifactId>tomcat7-maven-plugin</artifactId>
  <version>2.2</version>
  <configuration>
   <path>/</path>
   <tomcatUsers>src/main/webapp/config/tomcat-users.xml</tomcatUsers>
  </configuration>
 </plugin>

Running

To try examples, run embedded tomcat (configured in pom.xml of example project below):

mvn tomcat7:run-war

Output

Accessing http://localhost:8080/ and entering valid user name and password:

On submitting the form:

Refreshing the same page will not require to login again until the session expires.

Wait for session expiration until the following is printed in the console:

-- HttpSessionListener#sessionDestroyed invoked --

Now refreshing will forward to the login page:

Example Project

Dependencies and Technologies Used:

  • javax.servlet-api 3.1.0 Java Servlet API
  • JDK 1.8
  • Maven 3.5.4

Servlet - Forwarding to login page on session timeout Select All Download
  • servlet-session-timeout-and-login-forward
    • src
      • main
        • java
          • com
            • logicbig
              • example
                • MySecuredServlet.java
          • webapp
            • config

    See Also