【问题标题】:HttpSessionListener.sessionDestroyed() method is getting called twice during Session timeoutHttpSessionListener.sessionDestroyed() 方法在会话超时期间被调用两次
【发布时间】:2016-06-28 18:59:26
【问题描述】:

每当 HTTP 会话被破坏时,我都会尝试记录一条消息。 我在这个 Web 应用程序中使用 Spring Boot、Spring Security 和 Tomcat 8(嵌入式)。

在会话超时期间,sessionDestroyed() 方法被调用了 2 次​​strong>,所以我的消息被记录了两次。

我在两次调用期间检查了会话 ID 和 会话 ID 相同

这就是我的代码的样子...

import org.springframework.security.core.session.SessionRegistry;

...

        @Component
        public class MySessionListener implements javax.servlet.http.HttpSessionListener, ApplicationContextAware {
            @Autowired(required = false)
            SessionRegistry sessionRegistry;

下面是 sessionDestroyed()。

@Override
    public void sessionDestroyed(HttpSessionEvent se) {
        HttpSession session = se.getSession();

        SecurityContextImpl springSecurityContext = (SecurityContextImpl)session.getAttribute("SPRING_SECURITY_CONTEXT");
        if(springSecurityContext!=null){
            Authentication authentication = springSecurityContext.getAuthentication();
            LdapUserDetails userDetails = (LdapUserDetailsImpl)authentication.getPrincipal();

            WebAuthenticationDetails WebAuthenticationDetails = (WebAuthenticationDetails)authentication.getDetails();
            String userIp = WebAuthenticationDetails.getRemoteAddress();

            Log.info(userDetails.getUsername(),userIp,timestamp,"timeout or logout","session destroyed");

        }

       sessionRegistry.removeSessionInformation(se.getSession().getId());
        logger.info("Due to timeout/logout Session is Destroyed : Session ID is..." + session.getId());

    }

任何帮助将不胜感激...

注意:我注意到这个问题是 Tomcat 5 中的一个缺陷,我认为该缺陷在 Tomcat 8 中仍未修复。

参考:https://bz.apache.org/bugzilla/show_bug.cgi?id=25600

【问题讨论】:

    标签: spring servlets tomcat8


    【解决方案1】:

    这不是 Tomcat 的错误。这是我的应用程序特有的错误。

    我在我的应用程序中找到了以下代码。

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        if (applicationContext instanceof WebApplicationContext) {
            ((WebApplicationContext) applicationContext).getServletContext().addListener(this);
        } else {
            //Either throw an exception or fail gracefully, up to you
            throw new RuntimeException("Must be inside a web application context");
        }
    }
    

    下一行将当前监听器添加到 Servlet 上下文中。

    getServletContext().addListener(this);
    

    由于 Spring 已将此侦听器 (MySessionListener) 添加到 Servlet 上下文中,因此第二次添加侦听器导致 Tomcat 的 org.apache.catalina.session.StandardSession 类调用第二次 sessionDestroyed() 方法。

    Tomcat的源码供参考。

    package org.apache.catalina.session;
    
    public class StandardSession implements HttpSession, Session, Serializable {
    
    ....
    
    public void expire(boolean notify) {
    
    .....
    
    .....
    
     Object listeners[] = context.getApplicationLifecycleListeners();
                        if (listeners != null && listeners.length > 0) {
                            HttpSessionEvent event =
                                new HttpSessionEvent(getSession());
                            for (int i = 0; i < listeners.length; i++) {
                                int j = (listeners.length - 1) - i;
                                if (!(listeners[j] instanceof HttpSessionListener))
                                    continue;
                                HttpSessionListener listener =
                                    (HttpSessionListener) listeners[j];
                                try {
                                    context.fireContainerEvent("beforeSessionDestroyed",
                                            listener);
                                    listener.sessionDestroyed(event);
                                    context.fireContainerEvent("afterSessionDestroyed",
                                            listener);
                                }
    
    ....
    ....
    

    取自上面的Tomcat源代码..

    因此,listeners[] 包含 MySessionListener 的重复条目。

    Object listeners[] = context.getApplicationLifecycleListeners();
    

    【讨论】:

      猜你喜欢
      • 2018-06-27
      • 2018-10-31
      • 2021-11-04
      • 2013-05-29
      • 2021-09-23
      • 2013-12-31
      • 1970-01-01
      • 2015-03-10
      • 2011-09-21
      相关资源
      最近更新 更多