Tomcat 9 访问日志不显示通过 HttpSession + JSP + Servlet 登录的用户名(即 %u)

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

我想在 Tomcat 9 中包含 localhost_access_log 的用户名。 我的 LoginServlet 是:

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 ...

LoginFilter如下:

@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...

一切正常。

对于日志记录,在 server.xml 中,模式是:

<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" />

localhost_access_log显示IP地址等,除了用户名(只显示一个-)。如何在此处包含登录用户名 (servlet + HttpSession + jsp)。可能吗?任何替代解决方案?

谢谢。

模式 %u 为空,因为用户未根据 Tomcat 进行身份验证(参见 Authentication). You can leave your LoginServlet as it is and use the %{username}s placeholder instead of %u (cf. Access Log Valve)。

但是,您可以考虑使用 servlet 容器提供的身份验证方法。 Tomcat 当然有一个 Realm 实现可以满足您的需求,例如DataSourceRealm。因此你可以:

  1. META-INF/context.xml文件中配置一个默认的Realm,这样大部分用户只需配置一个数据源即可。那些有更具体需求的人可以覆盖上下文文件并配置完全不同的凭据来源,
  2. LoginServlet 中的代码替换为:
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. 要测试请求是否已通过身份验证,请使用 request.getRemoteUser() != null.