因此,对于我的webapp,如果我删除当前登录的用户,并且我想使他/她的会话无效。因此,只要他/她刷新页面或导航,他们就不再登录。我现在的方式是,如果用户成功登录,我会将用户对象存储在我的SessionScoped
bean中,并将HttpSession
存储到Application Map
。以下是我的代码
这是我的SessionScoped
bean
@PostConstruct
public void init() {
User user = UserDAO.findById(userId, password);
Map<String, Object> appMap = FacesContext.getCurrentInstance().
getExternalContext().getApplicationMap();
HttpSession session = (HttpSession) FacesContext.getCurrentInstance().
getExternalContext().getSession(false);
appMap.put(userId, session);
}
这是正确的做法吗?如果是这样,我该如何清理我的应用程序地图?
答案 0 :(得分:5)
这是一种正确的方法吗?
基本上有两种方式。
将用户ID作为键存储在应用程序范围中的HttpSession
句柄,以便您可以获取它并使其无效。这可能适用于在单个服务器上运行的小型Web应用程序,但可能无法在服务器群集上运行的Web应用程序上运行,具体取决于其配置。
我只会将它存储在应用程序范围内的另一个映射中,而不是像您一样直接存储在应用程序范围内,这样您就可以更轻松地了解所有用户,并且可以保证例如,任意用户ID不会与现有的应用程序范围的托管bean名称冲突。
在与每个HTTP请求检查的用户关联的某个DB表中添加一个新的布尔/位列。如果管理员将其设置为true
,则与请求关联的会话将失效,并且数据库中的值将重新设置为false
。
如何清理我的应用程序地图?
您可以使用HttpSessionListener#sessionDestroyed()
。 E.g。
public void sessionDestroyed(HttpSessionEvent event) {
User user = (User) event.getSession().getAttribute("user");
if (user != null) {
Map<User, HttpSession> logins = (Map<User, HttpSession>) event.getSession().getServletContext().getAttribute("logins");
logins.remove(user);
}
}
答案 1 :(得分:2)
我认为您可以使用您的方法(通过@BalusC提出的一些修改)以及一些通知机制(使其在分布式环境中工作)。您可以执行以下操作之一:
所有这些解决方案并不简单,但比每次请求轮询数据库服务器要快得多。