我目前正在维护一个@ApplicationScoped
bean 中所有当前活动的 HTTPSession 的 Map。(根据这里的建议,以及其他各种主题:Invalidate Session of a specific user)
我正在使用@WebListener
implementationHttpSessionListener
的sessionCreated
方法添加到当前会话列表中,并在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()"/>