javaservletstomcat9httpsessionaccess-log

Tomcat 9 access log does not show the username (i.e. %u) logged-in via HttpSession + JSP + Servlet


I want to include the username to localhost_access_log in Tomcat 9. My LoginServlet is:

if(r1.next() && username.equals(r1.getString(1))  && ...) {         
            HttpSession session = request.getSession();
            session.setAttribute("username", username);
            //setting session to expiry in 120 mins
            session.setMaxInactiveInterval(120*60);
            response.sendRedirect("system.jsp");
            // Close the database connections
            conn.close();
        } else ...

The LoginFilter is as follows:

@WebFilter( urlPatterns = {"/LoginFilter",  "/system.jsp", "/login.jsp" })
public class LoginFilter implements Filter {

@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
    HttpServletRequest request = (HttpServletRequest) req;
    HttpServletResponse response = (HttpServletResponse) res;
    HttpSession session = request.getSession(false);
    String loginURI = request.getContextPath() + "/login.jsp";
    boolean loggedIn = session != null && session.getAttribute("username") != null;
    boolean loginRequest = request.getRequestURI().equals(loginURI);
    
    if(loginRequest) {
        if (loggedIn) {
            response.sendRedirect(request.getContextPath() + "/system.jsp");
        }
        else {
            // if user has not logged in
            chain.doFilter(request, response);
        }} else...

Everything works fine.

For logging, in server.xml, the pattern is:

<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
               prefix="localhost_access_log" suffix=".txt"
               pattern="%{X-Forwarded-For}i %l %u %t &quot;%r&quot; %s %b" />

The localhost_access_log shows IP address, etc. except the user name (just shows a -). What to do to include the logged-in username here (servlet + HttpSession + jsp). Is it possible? Any alternative solutions?

Thank you.


Solution

  • The pattern %u is empty, because the user is not authenticated according to Tomcat (cf. Authentication). You can leave your LoginServlet as it is and use the %{username}s placeholder instead of %u (cf. Access Log Valve).

    However you might consider authentication methods provided by servlet containers. Tomcat has certainly a Realm implementation that suits your needs, e.g. the DataSourceRealm. Therefore you can:

    1. Configure in the META-INF/context.xml file a default Realm, so that most users need to just configure a datasource. Those with more specific needs can override the context file and configure an entirely different source of credentials,
    2. Replace the code in your LoginServlet with:
    try {
      request.login(username, password);
    } catch (ServletException e) {
      // deal with an authentication failure
      ...
      return;
    }
    final HttpSession session = request.getSession();
    // setting session to expiry in 120 mins
    session.setMaxInactiveInterval(120*60);
    response.sendRedirect("system.jsp");
    
    1. To test if a request is authenticated use request.getRemoteUser() != null.