【问题标题】:Perform custom event before Session Expiry in Spring在 Spring 的 Session Expiry 之前执行自定义事件
【发布时间】:2015-03-01 10:21:14
【问题描述】:

我是 Spring 框架的初学者。

在我的情况下,会话可以通过以下方式过期
--> 成功登出(显式登出)

--> 会话超时(隐式注销)

每当某些用户登录时,我都会在数据库中执行 DML(记录插入),并且每当用户会话超时(隐式注销)时,我想在数据库中执行 DML(记录删除)。

我的问题是 Spring 有什么方法可以在会话到期之前告诉我们。 所以我可以在会话到期之前执行我的自定义事件。

提前致谢

【问题讨论】:

  • 它很危险.. 如果您错过通知怎么办?如果您的应用在用户会话处于活动状态时出现故障怎么办?
  • 那我下一步该怎么做?
  • 这实际上取决于您在数据库中存储的记录以及这些记录的重要性..

标签: java spring hibernate session spring-mvc


【解决方案1】:

是的,您可以通过 SessionDestroyedEvent 做到这一点。

@Component
public class SessionEndedListener implements ApplicationListener<SessionDestroyedEvent> {

    @Override
    public void onApplicationEvent(SessionDestroyedEvent event)
    {
        for (SecurityContext securityContext : event.getSecurityContexts())
        {
            Authentication authentication = securityContext.getAuthentication();
            YourPrincipalClass user = (YourPrincipalClass) authentication.getPrincipal();
            // do something
        }
    }

}

在 web.xml 中:

<listener>
    <listener-class>
        org.springframework.security.web.session.HttpSessionEventPublisher
    </listener-class>
</listener>

此事件将在常规注销和会话超时时触发。

【讨论】:

  • 什么是你做不到的?除非您破解您正在使用的特定应用程序服务器,否则您无法在事前获取事件,您会在事后或事后获取事件。
  • 是的,我得到了解决方案@Codo,您的回答很有帮助。
  • 如果我采用这种方法,我是否需要依赖项中的“Spring Security”组件。在看到需要注册的 Listener 后,我就有了这个问题。
  • 我有一个 Spring Boot 应用程序,我实现了上面提到的 SessionEndedListener 来捕获 SessionDestroyEvent。我不必将 HttpSessionEventPublisher 注册为监听器,我只是想了解它是如何工作的?
  • 这对我不起作用,我是否必须使用 @EnableSpringHttpSession 注释或在某处注册应用程序侦听器?我需要为此启用 sessionRepository 吗?
【解决方案2】:

我已经通过类似@Codo 回答的方式解决了我的问题

@Component
public class SessionCreatedListenerService implements ApplicationListener<ApplicationEvent> {

private static final Logger logger = LoggerFactory
        .getLogger(SessionCreatedListenerService.class);

@Autowired
HttpSession httpSession;



@Override
public void onApplicationEvent(ApplicationEvent applicationEvent) {
    if(applicationEvent instanceof HttpSessionCreatedEvent){ //If event is a session created event



     }else if(applicationEvent instanceof HttpSessionDestroyedEvent){ //If event is a session destroy event
        // handler.expireCart();

         logger.debug(""+(Long)httpSession.getAttribute("userId"));

         logger.debug(" Session is destory  :" ); //log data

     }else if(applicationEvent instanceof AuthenticationSuccessEvent){ //If event is a session destroy event
         logger.debug("  athentication is success  :" ); //log data
     }else{
         /*logger.debug(" unknown event occur  : " Source: " + ); //log data
     }  
}   
}

【讨论】:

  • 在我的 Spring Boot 应用程序中的 Session Destroy 事件期间,我只能看到 applicationEvent 和 instanceof SessionDestroyedEvent ,而不是解决方案中提到的 HttpSessionDestroyedEvent 。那有什么区别?
  • HttpSessionDestroyedEventSessionDestroyedEvent 的直接子类,您可以在docs.spring.io/autorepo/docs/spring-security/3.2.5.RELEASE/… 的文档中看到
【解决方案3】:
import org.springframework.context.ApplicationListener;
import org.springframework.security.authentication.event.LogoutSuccessEvent;
import org.springframework.stereotype.Component;

@Component 

public class LogoutSuccessListener implements ApplicationListener<LogoutSuccessEvent>{

    @Override
    public void onApplicationEvent(LogoutSuccessEvent evt) {
         String login = evt.getAuthentication().getName();
         System.out.println(login + " has just logged out");
    } 
}

【讨论】:

  • 最好使用 LogoutSuccessEvent 。对我来说它工作正常,这是通用的解决方案
猜你喜欢
  • 1970-01-01
  • 2023-03-03
  • 1970-01-01
  • 1970-01-01
  • 2019-07-12
  • 1970-01-01
  • 2013-05-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多