【问题标题】:Session not invalidated properly, throwing "Session is invalid"会话未正确失效,抛出“会话无效”
【发布时间】:2017-05-24 07:23:46
【问题描述】:

我有一个使用 Wildfly 10 作为服务器的 JSF 2.2 应用程序。

用户已登录并添加到在线用户列表中:

HttpSession session = request.getSession();
funcionario.setSessao(session);
funcionario.setIp(request.getRemoteAddr());
session.setAttribute("usuarioLogado", funcionario);

我从在线用户列表中删除了注销的用户。

public class ActiveUserListener implements HttpSessionAttributeListene {

@Inject
Fixo fixo;

@Override
public void attributeAdded(HttpSessionBindingEvent event) {
    if (event.getValue() instanceof Funcionario) {
        fixo.getLogins().add((Funcionario) event.getValue());

    }
}

@Override
public void attributeRemoved(HttpSessionBindingEvent event) {
    if (event.getValue() instanceof Funcionario) {
        if (event.getValue() instanceof Funcionario) {
            fixo.getLogins().remove((Funcionario) event.getValue());
        }
    }
}

@Override
public void attributeReplaced(HttpSessionBindingEvent event) {
    if (event.getValue() instanceof Funcionario) {
        fixo.getLogins().add((Funcionario) event.getValue());
    }
} }

public class SessionCounter implements HttpSessionListener {

@Inject
Fixo fixo;

public void sessionDestroyed(HttpSessionEvent se) {
    if (se.getSession().getAttribute("usuarioLogado") != null) {            
        Funcionario f = fixo.getLogins().stream().filter(o -> o.getSessaoId().equals(se.getSession().getId()))
                .findAny().get();
        fixo.getLogins().remove(f);

    }
}

@Override
public void sessionCreated(HttpSessionEvent arg0) {
    // TODO Auto-generated method stub

}}´

当我尝试打印一些用户/会话详细信息时:

public void usuConsole() {
        System.out.println("nº " + fixo.getLogins().size());
        for (Funcionario f : fixo.getLogins()) {
            System.out.println(f.getMatricula());
            if (f.getSessao() != null) {
                System.out.println(f.getSessao().getId());
                System.out.println(f.getSessao().getCreationTime());
                System.out.println(f.getSessao().getLastAccessedTime());
            }
        }
    }

在某个点打印一些行:

会话无效 R5EB6hKAzanm50PSRYqxcv361UMD6nGjZWxJVc5P

如果很少用户登录是可以的,但是在很多用户登录和注销后,就会出现错误

【问题讨论】:

  • 你试过让这个线程安全吗?如果同时创建多个会话或同时创建一些会话,会发生什么情况?
  • 不行,我该怎么办?

标签: jsf wildfly httpsession


【解决方案1】:

选项 1:

尝试在 Fixo 类中为您的登录集合使用 java.util.concurrent.CopyOnWriteArrayList 实现。

选项 2

手动同步登录集合:

a) 使集合成为最终的(使用对象进行同步时的良好做法。

b) 在事件侦听器方法中同步登录集合插入和删除:

synchronized(fixo.getLogins()){
    fixo.getLogins().remove((Funcionario) event.getValue());
}

synchronized(fixo.getLogins()){
  fixo.getLogins().add((Funcionario) event.getValue());
}

c) 同步 for each 循环:

synchronized(fixo.getLogins()){

   for (Funcionario f : fixo.getLogins()) {
        System.out.println(f.getMatricula());
        if (f.getSessao() != null) {
           System.out.println(f.getSessao().getId());
           System.out.println(f.getSessao().getCreationTime());
           System.out.println(f.getSessao().getLastAccessedTime());
        }
   }
}

现在,在任何同步块中,对登录集合的任何公共方法调用都将被阻止,直到应用程序退出该块。 这意味着当 for each 循环正在运行时,事件侦听器方法中对集合的任何修改都将被保留,直到循环结束。 根据监听器规范,在 sessionDestroyed 方法完成处理之前,会话不会失效。

至少理论上是这样,试一试,看看效果如何。

【讨论】:

  • 我将列表更改为,现在我在线程“default task-79”中出现异常 java.lang.RuntimeException: org.jboss.weld.exceptions.UnsatisfiedResolutionException: WELD-001334: Unsatisfied dependencies对于带有限定符的 HttpSessionContext 类型'
  • ***.. 将列表更改为 java.util.concurrent.CopyOnWriteArrayList
  • Session无效的问题依然存在。
  • 明天我会尝试 2 选项
  • 让我更新,我实际上对第二个选项更感兴趣
猜你喜欢
  • 2016-04-23
  • 2013-06-29
  • 2014-12-24
  • 1970-01-01
  • 1970-01-01
  • 2015-04-26
  • 2018-08-05
  • 2015-06-30
  • 1970-01-01
相关资源
最近更新 更多