【问题标题】:Logback MDC - Wrong Value in SuccessHandlerLogback MDC - SuccessHandler 中的错误值
【发布时间】:2018-06-20 10:28:42
【问题描述】:

我正在尝试通过我的 Spring4 应用程序中的 logback 记录某些事件。 取自 logback 文档,我有以下 UserId 过滤器

@Component
public class UserIdFilter implements Filter {

    public static final String USERID = "userid";

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {}

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse    servletResponse, FilterChain filterChain) throws IOException, ServletException    {
        String userName = AccessLogger.getUserName();
        MDC.put(USERID, userName);
        try {
            filterChain.doFilter(servletRequest, servletResponse);
        } finally {
            MDC.remove(USERID);
        }
    }

    @Override
    public void destroy() {}
}

它根据请求将用户名设置为 MDC 中的“用户 ID”,并将用户名正确添加到日志输出(正在运送到 ELK 堆栈)

<appender name="LOGSTASH" class="ch.qos.logback.classic.sift.SiftingAppender">

    <filter class="de.app.log.PackageFilter">
        <level>de.app</level>
    </filter>

    <discriminator>
        <key>userid</key>
        <defaultValue>unknown</defaultValue>
    </discriminator>
    <sift>
        <appender name="LOGSTASH-SIFT" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
            <destination>elk:5000</destination>
            <encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
                <providers>
                    ...
                    <mdc/> 
                    <logstashMarkers/> 
                </providers>
            </encoder>
        </appender>
    </sift>
</appender>

我也在尝试记录成功的登录,其中尚未在 UserIdFilter 中设置“userid”,但用户之后会通过成功处理程序(在 WebSecurityConfigurerAdapter 中配置):

public class SimpleAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
    private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();

    private static final Logger LOG = LoggerFactory.getLogger(SimpleAuthenticationSuccessHandler.class);

    @Override
    public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {

        User user = (User) authentication.getPrincipal();
        String username = user.getUsername();
        MDC.put(UserIdFilter.USERID, username);
        LOG.info(LogEvent.LOGIN, user.toString());
        MDC.remove(UserIdFilter.USERID);
        redirectStrategy.sendRedirect(httpServletRequest, httpServletResponse, "/");
    }
}

然而 AuthenticationSuccessHandler 似乎遇到了某种并发问题,它从不同的用户那里获取 MDC 变量作为日志输出。结果是,某些登录事件从已经登录的用户那里获取用户 ID。以下日志事件,其中 MDC 再次通过 UserIdFilter 设置,似乎是正确的:

June 19th 2018, 15:14:35.602 | User: johndoe | event: submit | message: ChangeRequest submitted
June 19th 2018, 15:14:16.364 | User: johndoe | event: modified | message: Form modified
June 19th 2018, 15:06:47.567 | User: chris | event: login | message: de.app.User@5aa59640: Username: johndoe
June 19th 2018, 14:36:27.221 | User: chris | event: login | message: de.app.User@e7b516eb: Username: chris

-> 第 3 行:用户 johndoe 通过 MDC 获取 chris 作为登录事件的 userId

有人知道如何或在哪里正确实施/配置吗?

【问题讨论】:

    标签: spring logback mdc


    【解决方案1】:

    上述解决方案有效!

    我们曾在 SuccessHandler 中使用 LogStashMarker 而不是 MDC,并且由于分支 MDC 解决方案尚未正确发布到生产环境中,并且标记会导致不需要的行为。这也解释了为什么我们无法重现开发中的行为......呵呵!

    很抱歉占用您的时间,但也许上面的代码对某人有帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-06-06
      • 1970-01-01
      • 1970-01-01
      • 2018-04-24
      • 2016-01-18
      • 2021-07-12
      • 2019-05-21
      相关资源
      最近更新 更多