记录Web应用程序中用户活动的日志

14
我希望能够记录Web应用程序中的用户活动。我目前正在使用log4j,它可以很好地记录错误等日志,但是我不确定记录用户、执行的servlet方法和方法参数的最佳方法是什么。我正在使用Spring Security进行身份验证。
典型的servlet可能如下所示:
public class BankAccountServlet {
    @RequestMapping("/deposit")
    public void deposit(double amount) {
        ...
    }

    @RequestMapping("/checkBalance")
    public double checkBalance() {
        ...
    }
}

如果有两个用户,foo和bar,其中foo检查他的余额,而bar存入两笔现金10.00和5.00。我希望日志看起来像:

01/01/1970 23:59:59 - foo - checkBalance
02/01/1970 23:59:59 - bar - deposit - 10.00
02/01/1970 23:59:59 - bar - deposit - 5.00

如果有人能提供一些建议,我会非常感激他们的帮助。


2
这可能与上下文无关,但如果这是一个真正的银行应用程序,我会避免记录此类数据,除非确保日志有足够的保护。 - Vineet Reynolds
3个回答

36

使用Log4J的MDC/NDC功能实现并不难(SLF4J和Logback仅支持MDC)。

实现MDC过滤器

首先,实现一个servlet过滤器,将用户名添加到MDC/NDC中。Logback提供了方便的MDCInsertingServletFilter,Spring框架还将Log4jNestedDiagnosticContextFilter添加到存储中。可以参考它们的实现,但您需要像这样编写自定义过滤器:

public class UserToMdcFilter implements javax.servlet.Filter
{
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        MDC.put("user", SecurityContextHolder.getContext().getAuthentication().getPrincipal());
        try {
            chain.doFilter(request, response);
        } finally {
            MDC.remove("user");
        }
    }

    //...
}

将MDC值添加到日志模式中

确保在Spring安全过滤器之后在web.xml中应用此过滤器。 MDC功能非常棒-如果需要,它会将MDC线程本地映射中保存的所有值添加到每个日志记录语句中。 在您的情况下,只需添加以下内容:

%X{user}

格式 添加到您的日志记录中。

不显眼的日志记录方法参数/值

日志记录方法名称、参数和返回值由您决定(用户名将自动添加),但有一些优雅的方法可以完全消除样板日志记录代码。尝试使用这个Spring内置的切面:

<bean id="customizableTraceInterceptor" class="org.springframework.aop.interceptor.CustomizableTraceInterceptor">
    <property name="enterMessage" value="Entering $[methodName]($[arguments])"/>
    <property name="exitMessage" value="Leaving $[methodName](): $[returnValue]"/>
</bean>
<aop:config>
    <aop:advisor advice-ref="customizableTraceInterceptor" pointcut="execution(public * BankAccountServlet.*(..))"/>
</aop:config>

最终思考


是否有类似这样的Log4J2示例? - zygimantus

0

我过去使用过log4j来记录不仅仅是错误。我在代码中添加了INFO标签并更改了日志级别。这样,如果您决定不再需要记录这些活动,只需更改日志级别即可完成。希望这可以帮到您。


0
如果你想要记录服务器日志,可以使用ServletContext.log()方法,该方法使用容器的日志机制并将日志记录到容器日志中。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接