4

我目前正在维护一个@ApplicationScopedbean 中所有当前活动的 HTTPSession 的 Map。(根据这里的建议,以及其他各种主题:Invalidate Session of a specific user

我正在使用@WebListenerimplementationHttpSessionListenersessionCreated方法添加到当前会话列表中,并在sessionDestroyed.

管理员用户可以从 JSF (Richfaces 4.3.1) 页面访问此列表,并有选择地使特定会话无效。

问题是,当登录的管理员(会话 A)session.invalidate()从列表(例如会话 B)中选择并调用使用户的会话无效时,管理员的页面(或会话?)本身就会损坏,其中当前的链接/操作页面仍在处理中(我看到从控制台输出中命中操作方法),但没有重定向或导航工作(除了注销链接,它在会话 A 上调用无效,然后成功重定向到登录页面)。控制台中没有显示错误或警告,即使在关闭浏览器窗口并将其重新打开到同一会话 (A) 后,这种破坏行为仍然存在。

通过查看 Chrome 的网络选项卡,我看到每次重定向尝试都会创建一个单独的 POST,但没有别的。

我们的大部分导航都是在 faces-config.xml 中设置的,如下所示:

<navigation-case>
        <from-action>#{logoutAction.doLogout}</from-action>
        <to-view-id>/login.xhtml</to-view-id>
        <redirect/>
</navigation-case>

我完全没有想法,特别是因为所有在线建议似乎都指向我目前正在做的事情......有人可以解释为什么会发生这种情况,或者推测我可能做错了什么或如何解决它?

谢谢,如果需要任何更好的信息,请告诉我。

使用:

  • Java EE 6
  • JSF 2.1
  • Jboss AS 7.1.1
  • Richfaces 4.3.1

编辑:

缩减代码示例...

保存会话映射的 Bean(每个都在自定义包装对象中SessionUserFacade,以保存其他用户信息):

@Named
@ApplicationScoped
public class AppSessionsStateBean implements Serializable {

    private final Map<String, SessionUserFacade> currentSessions = Collections.synchronizedMap(new HashMap<String, SessionUserFacade>());

    public void addSession(HttpSession session) {
        currentSessions.put(session.getId(), new SessionUserFacade(null, session));
    }

    public void removeSession(HttpSession session) {
        currentSessions.get(session.getId()).setSession(null);
        currentSessions.remove(session.getId());
    }

    public Map<String, SessionUserFacade> getCurrentSessions() {
        return currentSessions;
    }
}

简单的 @WebListener 来调用应用范围的 bean:

@WebListener
public class SessionListener implements HttpSessionListener{

    @Inject
    private AppSessionsStateBean appStateBean;

    @Override
    public void sessionCreated(HttpSessionEvent httpSessionEvent) {
        appStateBean.addSession(httpSessionEvent.getSession());
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
        appStateBean.removeSession(httpSessionEvent.getSession());
    }
}

在 bean 中从前端访问的操作方法@Named @ViewAccessScoped(invalidateSession 只是 的直接包装器HttpSession.invalidate();):

public void invalidateSelected() {

    for (SessionUserFacade session : selectionItems) {

        if (session.isLoggedIn()) {
            session.invalidateSession();
        }
    }
    clearSelection();
}

调用自:

<a4j:commandButton id="btnConfirmLogout" action="#{sessionManagementAction.invalidateSelected}"
        value="Logout Selected" oncomplete="#{rich:component('forceLogoutPopup')}.hide()"/>
4

0 回答 0