每当HTTP Session被销毁时,我都会尝试记录消息。 我在此Web应用程序中使用 Spring Boot,Spring Security和Tomcat 8 (嵌入式)。
在会话超时期间, sessionDestroyed()方法被调用2次,因此我的消息会被记录两次。
我在两次调用期间都检查了会话ID,会话ID是SAME 。
这就是我的代码的样子......
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中的缺陷仍未修复。
答案 0 :(得分:0)
这不是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 Context中。
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();