Invalidate Session of a specific user

时光毁灭记忆、已成空白 提交于 2019-12-04 04:51:13

问题


So for my webapp, if I remove a user that is currently logged in, and I want to invalidate his/her session. So that as soon as he/she refresh the page or navigate, they are no longer log in. The way I have now is that if a User logged in successfully, I will store the user object in my SessionScoped bean, and store the HttpSession to the Application Map. Below is my code

This is my 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);
}

Is this a correct approach? If so, how do I clean up my application map?


回答1:


Is this a correct approach?

There are basically 2 ways.

  1. Store the HttpSession handle in the application scope by the user ID as key so that you can get a handle of it and invalidate it. This may work for a small web application running on a single server, but may not work on a web application running on a cluster of servers, depending on its configuration.

    I would only store it in another map in the application scope, not directly in the application scope like as you did, so that you can easier get an overview of all users and that you can guarantee that an arbitrary user ID won't clash with an existing application scoped managed bean name, for example.

  2. Add a new boolean/bit column to some DB table associated with the user which is checked on every HTTP request. If the admin sets it to true, then the session associated with the request will be invalidated and the value in the DB will be set back to false.


how do I clean up my application map?

You could use HttpSessionListener#sessionDestroyed() for this. 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);
    }
}



回答2:


I think you can use your approach (with some modifications proposed by @BalusC) plus some notification mechanism (to make it work in distributed environment). You can do one of the following:

  1. Use a topic queue subscribed by all your servers. When you remove user from your admin panel the JMS message will be created and sent to the topic. Every server will be responsible for invalidating the user session if it exists on the particular server (if the session is referenced in servletContext map).
  2. Implement some action to invalidate the user session and run this action on every server in the cluster (The admin panel should send HTTP request to every server).
  3. Use JGroups and TCP reliable multicast.

All of these solutions are not simple but much faster than polling the DB server on every request.



来源:https://stackoverflow.com/questions/9219393/invalidate-session-of-a-specific-user

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!