1 2 Previous Next 15 Replies Latest reply on Nov 12, 2009 4:35 PM by maristea1

    How can I invalidate a user's http session?

    maxradin

      I want to be able to force off a user's session. How can I get hold of a user's HttpSession using seam?
      thanks
      Max

        • 1. Re: How can I invalidate a user's http session?
          dan.j.allen

          How can I access the HttpServletRequest or HttpSession Directly?


          However, you should be using #{webSession.invalidate} to let Seam cleanup before the session is actually terminated.

          • 2. Re: How can I invalidate a user's http session?
            maxradin

            Thanks Dan
            But what I need to do is to be able to clean up sessions users have left logged on via an admin UI (when they don't explicitly log off and close their browser etc.) Our session timeout is 30 minutes so they can take a while. I also need this for security reasons when a user has been removed from the system. I want to provide a list of open sessions and have the capability to grab a user, find his (or her) HttpSession and invalidate it on demand. If I can create an identity object for a given user on the fly and force logout on it that would work as well but the only way I am aware of is when seam injects an identity object for the current logged on user. I could probably keep my own map of sessions on login but was hoping their might be some functionality within seam.
            Max

            • 3. Re: How can I invalidate a user's http session?
              dan.j.allen

              Oh, I see. You want to be able to grab another person's HttpSession. I missed that, sorry.


              Try this for starters. You have to maintain your own list as sessions come and go.


              public class SessionCollectorListener implements ServletContextListener, HttpSessionListener {
              
                  private static final LogProvider log = Logging.getLogProvider(SessionCollectorListener.class);
              
                  public static final String SESSION_LIST_KEY = "com.domain.infra.web.sessionList";
              
                  public void contextInitialized(ServletContextEvent e) {
                      e.getServletContext().setAttribute(SESSION_LIST_KEY, new ArrayList());
                  }
              
                  public void contextDestroyed(ServletContextEvent e) {}
              
                  public void sessionCreated(HttpSessionEvent e) {
                      ((List) e.getSession().getServletContext().getAttribute(SESSION_LIST_KEY)).add(e.getSession());
              
                      if (log.isDebugEnabled()) {
                          log.debug("Session created; session id = " + e.getSession().getId());
                          logNumberOfSessions(e);
                      }
                  }
              
                  public void sessionDestroyed(HttpSessionEvent e) {
                      ((List) e.getSession().getServletContext().getAttribute(SESSION_LIST_KEY)).remove(e.getSession());
              
                      if (log.isDebugEnabled()) {
                          log.debug("Session destroyed; session id = " + e.getSession().getId());
                          logNumberOfSessions(e);
                      }
                  }
              
                  private void logNumberOfSessions(HttpSessionEvent e) {
                      log.debug("Number of active sessions: " + ((List) e.getSession().getServletContext().getAttribute(SESSION_LIST_KEY)).size());
                  }
              }



              Then you can do something like sum the size of all the sessions:


              @Name("sessionControl")
              public class SessionControl {
              
                   @Logger
                   private Log logger;
              
                   @In
                   protected FacesContext facesContext;
                   
                   @Factory("currentSessionSize")
                   public int getCurrentSessionSize() {
                        HttpSession currentSession = getCurrentSession();
                        if (currentSession == null) {
                             return 0;
                        }
              
                        return calculateSessionSize(currentSession);
                   }
                   
                   @Factory("totalSizeOfSessions")
                   public int getTotalSizeOfSessions() {
                        int totalBytes = 0;
                        for (HttpSession session : getSessions()) {
                             totalBytes += calculateSessionSize(session);
                        }
                        
                        return totalBytes;
                   }
                   
                   public void flushBackgroundSessions() {
                        HttpSession currentSession = getCurrentSession();
                        List<HttpSession> sessions = new CopyOnWriteArrayList<HttpSession>(getSessions());
                        for (HttpSession session : sessions) {
                             if (!session.equals(currentSession)) {
                                  session.invalidate();
                             }
                        }
                   }
                   
                   protected int calculateSessionSize(HttpSession session) {
                        int totalBytes = 0;
                        try {
                             ByteArrayOutputStream baos = new ByteArrayOutputStream();
                             ObjectOutputStream oos = new ObjectOutputStream(baos);
                             logger.trace("Calculating session size for session id: " + session.getId());
                             for (Iterator<String> iter = new EnumerationIterator<String>(session.getAttributeNames()); iter.hasNext();) {
                                  String name = iter.next();
                                  oos.writeObject(session.getAttribute(name));
                                  int size = baos.size();
                                  logger.trace("Session attribute name: " + name + "; session attribute size: " + size + "b");
                             }
                             oos.flush();
                             totalBytes = baos.size();
                             oos.close();
              
                             logger.trace("Total session size: " + totalBytes + "b");
                        } catch (Exception e) {
                             logger.error("Could not get the session size", e);
                             totalBytes = -1;
                        }
                        
                        return totalBytes;
                   }
                   
                   protected HttpSession getCurrentSession() {
                        return (HttpSession) facesContext.getExternalContext().getSession(false);
                   }
                   
                   protected List<HttpSession> getSessions() {
                        Context applicationContext = Contexts.getApplicationContext();
                        return (List<HttpSession>) applicationContext.get(SessionCollectorListener.SESSION_LIST_KEY);
                   }
                   
              }



              Hopefully you can extrapolate from that.

              • 4. Re: How can I invalidate a user's http session?
                maxradin

                Thanks, Dan-
                This is what I think I need. I'll let you know how it works out.
                Max

                • 5. Re: How can I invalidate a user's http session?
                  michaeltr

                  Hi Dan


                  that sounds good. But a few more questions:
                  As far as I understand I need the webSession for the Seam cleanup. So how can I get the webSession?
                  The other question is how to get injected data from the session e.g. the username?


                  Thanks


                  Michael

                  • 6. Re: How can I invalidate a user's http session?
                    maxradin

                    Hi Dan-
                    I implemented the SessionCollectionListener but it's not being called.
                    I see it instantiated and loaded on startup. I added a name annotation. Any ideas?
                    thanks
                    Max

                    • 7. Re: How can I invalidate a user's http session?
                      maxradin

                      Hi Dan-
                      I got it to work. I forgot to register the listener in my web.xml.
                      It all works altho' I get an illegal state exception saying I should use the invalidate on the webSession interface but it still works fine. User is logged out.
                      thanks a lot.
                      Max

                      • 8. Re: How can I invalidate a user's http session?

                        Hi Max


                        how it works - how can we configure this SessionCollectorListener in seam and also how we configure seam filter for this? bcoz i have also this doubt that am trying to remove the user in application context while their session timeout? please tell me vry urgent


                        thank you

                        • 9. Re: How can I invalidate a user's http session?
                          dan.j.allen

                          You really can't use the Seam filter because you are working outside of the servlet request/response life cycle when you are manipulating background HttpSession objects. This really isn't sanctioned by the spec. You could get a handle on Seam's webSession component by digging through the session, but still it wouldn't do you much good because you are outside of the Seam life cycle for that session object. It just doesn't serve the same purpose in that context.


                          I'm not sure I understand your point about removing the user from application context.

                          • 10. Re: How can I invalidate a user's http session?
                            maxradin

                            BTW, I'm using the sample code you provided Dan and it works great for tracking sessions and forcing off users. This is required as our clients want to be able to kill sessions for users who are no longer allowed on the system as well as users who have closed their browser and not gone through an orderly logoff. We have a single login only approach per user so this is quite helpful.


                            I have not had any luck with the websession.invalidate. It would be ideal if seam could provide a mechanism to do this.
                            Max

                            • 11. Re: How can I invalidate a user's http session?
                              gus888

                              Hi Dan,


                              Thanks a lot for your codes. I have a question. When I navigated to login.xhtml page (I haven't logged in), the sessionCreated was invoked automatically. In addition, when I logged out, and system would navigate to login.xhtml page,  the sessionDestroyed was invoked first, then the sessionCreated was invoked again. Since I haven't logged in, but my session was already created. Is it correct? Based on this situation, how can I know who is online (e.g. my friends). Thank you for advice in advance.

                              • 12. Re: How can I invalidate a user's http session?
                                dan.j.allen

                                I suppose you would have to peek into the session and look for a token that is present when the user is logged in. Having a session doesn't mean logged in, it means the person as visited the site recently.

                                • 13. Re: How can I invalidate a user's http session?
                                  maxradin

                                  Dan-
                                  That is correct. We monitor a session during authentication, putting the user name in the session. This is how I monitor session usage. You're right, there can be discrepancies on logout and session unbound, but I've found them to be close enough to work for this functionality.

                                  • 14. Re: How can I invalidate a user's http session?
                                    gus888

                                    Thanks a lot, Dan.


                                    I use the following codes to track session's username:

                                              
                                    Identity identity = (Identity)currentSession.getAttribute(SESSION_ATTR_IDENTITY);
                                    if (identity != null && identity.getPrincipal() != null)
                                         username = identity.getPrincipal().getName();



                                    Another general question, for a high visited site, what is acceptable session size as usual? 10 - 50KB? which maybe depend on system hardware, e.g. memory. Thanks.

                                    1 2 Previous Next