10 Replies Latest reply on Feb 21, 2011 12:34 AM by ananymous7239

    Stopping users to have multiple sessions

    zahidmaqbool

      Hi, I am stuck into some problem where I cannot identify how can it be done. The requirement is that a user should not be able to have multiple sessions. That is once he logs in. He cannot log in again from a different machine. But if the user is inactive for 15 minutes then allow him to login again. So if a session is expired then what event would we get in seam. Also I was wondering what if the user never logs in or browser window closes/crashed, how would our application come to know about this. Is this possible even at all..



      Thanks a lot for your help



        • 1. Re: Stopping users to have multiple sessions
          mcoffin

          You could achieve limiting a the number of sessions per user by  implementing Acegi and Spring.


          Because HTTP is a stateless protocol it's hard to detect if the user's browser has crashed, closed the browser, etc. 


          The only way I could see to do this is to have javascript on each page (via ajax) send a heartbeat to a servlet which would keep the session alive. 


          If a heartbeat wasn't received in specified period of time say 30 seconds, the servlet would kill the session.


          You would also have write your own logic, to time out the session .  Since the heartbeat will not work with the standard way of timing out sessions. 


          You would have to use Acegi security instead of Seam's.  Here's how you would kill the session.


          Acegi Concurrent Sessions (kicking logged in users)



          • 2. Re: Stopping users to have multiple sessions
            rgustav

            Unless you're running a single JVM (ie. non-clustered), you probably would need to update the Acegi trick to be cluster aware.


            Clustering Acegi


            If you're not using Acegi, a simple approach would be to record user session creations into a database, noting the sessionId, userId and activityTime.  Update the activityTime with each HTTP request, and clear the record when the session is destroyed (use a session listener).  On Login, simple check for an active session record for the user which is not too old.


            You can even get fancy, allowing the 2nd session to kill the 1st session (ie. add a check to ensure the session is still active when processing each HTTP request, the 1st session will see it is inactive, and not process the request, and kill itself off).  Depending on how you had Seam managing conversation state, I imagine it's even possible to go totally off the deep end and allow the 2nd session to take control of the 1st session entirely (e.g. transfer the conversation state between the sessions).


            Also, a cluster aware Hibernate 2nd level cache could help implement this efficiently by reducing (even eliminating?) database IO.

            • 3. Re: Stopping users to have multiple sessions
              mcoffin

              Ah yes clusters, the bain of my existence.


              The problem with using the database and a session listener in clustered environment is that if a machine with user's session goes down, HttpSessionListener.sessionDestroyed() might not get called, leaving the user locked out of the application.


              Also, if you allow a session to destroy another session, it defeats the purpose of limiting the number of sessions a user can have.


              To get around the clustering issue with Acegi have a look here:


              Clustering Acegi via JGroups (DistributedHashtable)


              • 4. Re: Stopping users to have multiple sessions
                zahidmaqbool

                Thanks a lot for your help.. I will try doing this. If I face any problems, I would come back to you guys!!! :))

                • 5. Re: Stopping users to have multiple sessions
                  zahidmaqbool

                  Just a simple question, what steps would I need to take to use Acegi. Also do I need to disable Seam Security from some where??

                  • 6. Re: Stopping users to have multiple sessions
                    jabinara

                    Hello Zahid. 
                    I am facing the same problem that you have mentioned in the blog.  I want that with one username only one user can be logged in, multiple users with same username should not be be able to login.  Can you please help me out, if you have got the answer.


                    I was trying to get all the active sessions in the application and then check for the username.  But the problem I am facing is I am not able to get all the active sessions.  So please help.


                    You can mail me too.
                    Waiting for the reply.  Please reply soon.


                    Any body else who knows the fix can also reply.


                    Thnx
                    JB

                    • 7. Re: Stopping users to have multiple sessions
                      janakiramnarla

                      Hi,
                        Can anybody has information on this issue, please reply to me .I am also struck with the same.

                      • 8. Re: Stopping users to have multiple sessions
                        raphaufrj

                        Anyone can share your knowledge with us?

                        • 9. Re: Stopping users to have multiple sessions
                          lvdberg

                          Hi,


                          I included piece of code of a Session bean I use in my application.


                          I kick-start this watchdog in my authentication bean (the standard Seam way of authenticating a User) , set a boolean in the DB that the user is logged in and call the start method of this watchdog. It is session scoped so it is in memory as long as the session of the specific user is valid. At the moment the user logs out, the destoy method is called and the boolean is cleared. The same happens if the user closes the browser without logging out (with a session time out).


                          You can improve the code by using a timer or resetting a timer value when accessing pages etc.



                          @Name("sessionWatchdog")
                          @Scope(ScopeType.SESSION)
                          @AutoCreate
                          public class SessionWatchdog implements Serializable{
                          
                          
                          private String  userName;
                               
                          public void start(String u){
                            userName = u;
                          }
                               
                          
                          @Destroy
                          @Transactional
                          public void destroy(){
                               if (userName != null){
                                    try {
                                       Query q = entityManager.createQuery("select u from User u where u.userName = :name");
                                   q.setParameter("name", userName);
                                   User user = (User) q.getSingleResult();
                                   user.setConnected(YesNoEnum._no);
                                   entityManager.merge(user);
                                   entityManager.flush();
                                   } catch (Exception e){
                                   log.error("captured an error while closing the session");
                                   }
                               log.info("sessionStarter destroyed for user " + userName);
                               } else log.info("No valid userName, but the session was destroyed");
                               }
                          }




                          Hopefully useful for you.


                          Leo

                          • 10. Re: Stopping users to have multiple sessions
                            ananymous7239


                            Hi Zahid i want to save 5 uploaded images as 5 records in Database
                            .you have any idea about this please help me .i am able to save only the last upload 
                            image. this is my persist method
                            @Override
                                 @Begin(join = true)
                                 @End
                                 public String persist() {
                                      try {
                                           BeanUtils.copyProperties(getInstance(), doImageUpload);
                            
                                           for (int num = 0; num < files.size(); num++) {
                            
                                                getInstance().setData(files.get(num).getData());
                                                getInstance().setLength(files.get(num).getData().length);
                                                log.info("...............files in persist"+files.get(num).getLength());
                                                log.info("...............files in persist"+files.size());
                                                log.info("...............files in persist"+files.get(num).getData());
                            
                                           }
                                           super.persist();
                            
                                      } catch (Exception e) {
                                           log.info("exception" + e);
                                      }
                                      return "done";
                            
                                 }