使特定用户的会话无效

时间:2012-02-09 21:53:24

标签: jsf session login invalidation

因此,对于我的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);
}

这是正确的做法吗?如果是这样,我该如何清理我的应用程序地图?

2 个答案:

答案 0 :(得分:5)

  

这是一种正确的方法吗?

基本上有两种方式。

  1. 将用户ID作为键存储在应用程序范围中的HttpSession句柄,以便您可以获取它并使其无效。这可能适用于在单个服务器上运行的小型Web应用程序,但可能无法在服务器群集上运行的Web应用程序上运行,具体取决于其配置。

    我只会将它存储在应用程序范围内的另一个映射中,而不是像您一样直接存储在应用程序范围内,这样您就可以更轻松地了解所有用户,并且可以保证例如,任意用户ID不会与现有的应用程序范围的托管bean名称冲突。

  2. 在与每个HTTP请求检查的用户关联的某个DB表中添加一个新的布尔/位列。如果管理员将其设置为true,则与请求关联的会话将失效,并且数据库中的值将重新设置为false


  3.   

    如何清理我的应用程序地图?

    您可以使用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提出的一些修改)以及一些通知机制(使其在分布式环境中工作)。您可以执行以下操作之一:

  1. 使用所有服务器订阅的主题队列。从管理面板中删除用户时,将创建JMS消息并将其发送到主题。如果用户会话存在于特定服务器上(如果在servletContext映射中引用了会话),则每个服务器都将负责使用户会话失效。
  2. 实施一些操作以使用户会话无效并在群集中的每个服务器上运行此操作(管理面板应向每个服务器发送HTTP请求)。
  3. 使用JGroups和TCP可靠多播。
  4. 所有这些解决方案并不简单,但比每次请求轮询数据库服务器要快得多。