CDI/JSF如何处理会话超时

发布于 2025-01-30 15:53:34 字数 1779 浏览 3 评论 0 原文

我有一个jakarta EE8(CDI 2 / WELD / JSF 2.3 / WILDFLY)应用程序,在该应用程序中,我需要在用户注销时执行一些清理代码,手动注销还可以,但是现在我需要在会话自动发生注销时启动事件超时,为了处理此问题,我已经尝试了以下两种方法...

@Named
@SessionScoped
public class HttpSessionObservers implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    
    @Inject private Logger log;
    @Inject SecurityContext securityContext;

    @PreDestroy
    public void processSessionScopedDestroying() {
        
        log.debug("Http Session predestroy");   
        Principal principal = securityContext.getCallerPrincipal(); //<----is null
        //...do some cleanup/logging operations on user account
    }

}

上面的 @predestroy 在会话时间播放时呼叫射击,但是登录用户(principal)始终是无效的已经登录了,因此我无法获得用户。

@Named
public class HttpSessionObservers implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    
    @Inject private Logger log;
    @Inject private Event<UserLogoutEvent> userLogoutEvent;
    
    public void processSessionScopedInit(@Observes @Initialized(SessionScoped.class) HttpSession payload) {
        log.debug("Http Session initialised");
    }

    public void processSessionScopedDestroying(@Observes @BeforeDestroyed(SessionScoped.class) HttpSession payload) {
        //Never fires
        log.debug("Http Session predestroy");   
        Principal principal = securityContext.getCallerPrincipal();
        //...do some cleanup/logging operations on user account
    }

    public void processSessionScopedDestroyed(@Observes @Destroyed(SessionScoped.class) HttpSession payload) {
        log.debug("Http Session destroyed");    
    }
}

在这里,@beforedestroy的事件从未被解雇,似乎找不到任何工作的示例,它确实可以适合其他范围。

I have a Jakarta EE8 ( CDI 2 / Weld / JSF 2.3 / Wildfly ) app where I need to execute some cleanup code when the user logs out, manual logout are fine however I now need to fire an event when logout happens automatically due to session timeout, to handle this I have tried the following two methods already...

@Named
@SessionScoped
public class HttpSessionObservers implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    
    @Inject private Logger log;
    @Inject SecurityContext securityContext;

    @PreDestroy
    public void processSessionScopedDestroying() {
        
        log.debug("Http Session predestroy");   
        Principal principal = securityContext.getCallerPrincipal(); //<----is null
        //...do some cleanup/logging operations on user account
    }

}

The above @PreDestroy callback fires when the session times out but the logged in user (principal) is always null so it seems they have already been logged out so I cannot obtain the user.

@Named
public class HttpSessionObservers implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    
    @Inject private Logger log;
    @Inject private Event<UserLogoutEvent> userLogoutEvent;
    
    public void processSessionScopedInit(@Observes @Initialized(SessionScoped.class) HttpSession payload) {
        log.debug("Http Session initialised");
    }

    public void processSessionScopedDestroying(@Observes @BeforeDestroyed(SessionScoped.class) HttpSession payload) {
        //Never fires
        log.debug("Http Session predestroy");   
        Principal principal = securityContext.getCallerPrincipal();
        //...do some cleanup/logging operations on user account
    }

    public void processSessionScopedDestroyed(@Observes @Destroyed(SessionScoped.class) HttpSession payload) {
        log.debug("Http Session destroyed");    
    }
}

Here, the @BeforeDestroyed event is never fired, cannot seem to find any examples of this working, it does work ok for other scopes.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

绝不放开 2025-02-06 15:53:34

实现您自己的 httpsessionlistener 并用 @weblistener 进行注释。容器应识别此问题,并将在您的实现中调用 sessionDestroyed()方法。您的课程有资格参加CDI注入,因此在 sessiondestroyed()中,您可以发射事件并与CDI观察者一起收听。

参考:

编辑:

然后尝试以下操作:范围: httpsessionlistener inmand inmand to @ApplicationsCoped 。具有SessionID/用户名的同步图。在 sessionCreated()中,插入地图中,然后在 sessionDestroyed()中将其删除在最后 block中。

该容器还将有几个隐式 httpsessionListener s,因此在会话无效之后很长时间您的最后一个被称为您的最后一次。如果这样,您可以使用另一种技术来插入您的 httpsessionListener inmpriond。首先尝试上述技术,然后我们可以深入研究。

Implement your own HttpSessionListener and annotate it with @WebListener The container should recognize this and will call the the sessionDestroyed() method in your implementation. Your class is eligible for CDI Injection so in sessionDestroyed(), you can fire an event and listen for it with a CDI Observer.

Ref: https://docs.oracle.com/javaee/6/api/javax/servlet/http/HttpSessionListener.html

EDIT:

Try this then: Scope your HttpSessionListener impl to @ApplicationScoped. Have a synchronized Map of sessionId/username. In sessionCreated() insert into the map, and on sessionDestroyed() remove it in a finally block.

The container will also have several implicit HttpSessionListeners, so there's a chance yours is being called last long after the session is invalidated. If thats the case, there's another technique you can use to insert your HttpSessionListener impl first. Try the above technique first then we can dive into this.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文