6 Replies Latest reply on Jul 30, 2007 8:08 PM by Ricardo Memoria

    login & logout options

    Caye Newbie

      Hi! I'm a web developer from finland and i have been working with Jboss/Seam for 2 months, so i just decided to join this forum, since i was reading on it everyday :D

      My question is the next one, i want to save some statistics about my users when they log in & out into/from the web (like date of login or date of logout, and things like that). For that i create a method that handles the whole process, but my question is how can i call to those methods once the user execute the action of log in or out.

      I tried with the pages.xml with this code, but doesnt work:

      <navigation from-action="#{identity.login}">
      <action execute="#{usereditor.setLoginDate}"/>
      <redirect view-id="/home"/>
      </navigation>


      Thanks in advance for the answer, and i hope to help with some post aswell in the future! ;)

        • 1. Re: login & logout options
          Ricardo Memoria Novice

          For the login process you may create a bean with a method returning a boolean value and map it in components.xml like that:

          <security:identity authenticate-method="#{authenticator.authenticate}"
           security-rules="#{securityRules}"/>


          It'll call the authenticate method of your bean, and you can put your code for the login event.

          For the logout you must map the org.jboss.seam.preDestroyContext.SESSION also in components.xml like that:

          <event type="org.jboss.seam.preDestroyContext.SESSION">
           <action expression="#{authenticator.logout}"/>
          </event>


          Hope I've helped.

          regards,
          Ricardo Memória

          • 2. Re: login & logout options
            Alex Ka Novice

            I think login/logout fires an event that you can catch. For example in components.xml you should have:

            <event type="org.jboss.seam.postAuthenticate">
             <action expression="#{redirect.returnToCapturedView}"/>
            </event>


            Also, the login method of identity can call a method from a custom component. In components.xml you need :
            <security:identity authenticate-method="#{authenticator.authenticate}"/>


            And declare a method:
            public boolean authenticate()


            That will return login successful/unsuccessful. In this method you can log data.

            Not so sure what to do with the logout but I hope you'll figure it out. Ops, Ricardo was first...

            • 3. Re: login & logout options
              Caye Newbie

              Thanks a lot! Il'l try and tell you how it works...

              • 4. Re: login & logout options
                Gavin King Master

                There are some events that occur on login/out that you can write an @Observer method for.

                • 5. Re: login & logout options
                  Caye Newbie

                  I have been working with it and the login works perfectly with the solution that Ricardo gave me (thanks a lot!), but the logout is a little bit more difficult, it looks like its impossible to persist the object if i try to do it using the org.jboss.seam.preDestroyContext.SESSION. I have been reading one post of you Ricardo and it seems that you fixed making a stateless session bean and changing the entityManager to @PersistenceContext instead of @In.

                  But for me i dont know why doesn't work, is it possible to check out somewhere the events that occur when someone login/out? Then i can try to use the @Observer that seems a better way

                  This is the code:

                  components.xml

                  <event type="org.jboss.seam.preDestroyContext.SESSION">
                   <action expression="#{userHandler.setLogoutDate(authenticatedUser)}"/>
                  </event>


                  UserHandler

                  public void setLogoutDate(CustomUser user) {
                   int numberDates = user.getUserstatistics().getLoginDates().size();
                   CustomDate loginDates = user.getUserstatistics().getLoginDates().get(numberDates-1);
                   em.merge(loginDates);
                   loginDates.setLoggedOut(new Date());
                   Date timeBetween = new Date(); timeBetween.setTime(loginDates.getLoggedIn().getTime()-loginDates.getLoggedOut().getTime());
                   loginDates.setTimeBetween(timeBetween);
                   em.persist(loginDates);
                   em.flush();
                   log.info("User logged out at "+loginDates.getLoggedOut().toString());
                   }


                  • 6. Re: login & logout options
                    Ricardo Memoria Novice

                    Hi Caye,

                    This is my authenticator bean:

                    @Name("authenticator")
                    @Stateless
                    public class AuthenticatorBean implements Authenticator {
                    
                     @In(required=false) @Out(required=false)
                     UserLogin userLogin;
                    
                     @In Identity identity;
                    
                     @In(create=true) FacesMessages facesMessages;
                    
                     @PersistenceContext EntityManager entityManager;
                    
                    
                     public boolean authenticate()
                     {
                     String pwd = Passwords.hashPassword(identity.getPassword());
                    
                     try {
                     User user = (User)entityManager.createQuery("from User u where u.login = :login " +
                     "and upper(u.password) = :pwd")
                     .setParameter("login", identity.getUsername().toUpperCase())
                     .setParameter("pwd", pwd.toUpperCase())
                     .getSingleResult();
                    
                     if (user.getRoles().size() == 0) {
                     facesMessages.addFromResourceBundle("login.norole");
                     return false;
                     }
                    
                    
                     // saves login info
                     FacesContext facesContext = FacesContext.getCurrentInstance();
                     HttpServletRequest req = (HttpServletRequest) facesContext.getExternalContext().getRequest();
                     String ipAddr = req.getRemoteAddr();
                     String app = req.getHeader("User-Agent");
                    
                     userLogin = new UserLogin();
                     userLogin.setUser(user);
                     userLogin.setLoginDate(new java.util.Date());
                     if (app.length() > 80)
                     app = app.substring(0, 80);
                     userLogin.setApplication(app);
                     userLogin.setIpAddress(ipAddr);
                     entityManager.persist(userLogin);
                    
                     for (UserRole r: userLogin.getUser().getRoles()) {
                     identity.addRole(r.getName());
                     }
                    
                     return true;
                     }
                     catch (NoResultException e) {
                     e.printStackTrace();
                     return false;
                     }
                     }
                    
                    
                     public void logout() {
                     if ((userLogin != null)&&(userLogin.getLogoutDate() == null)) {
                     userLogin = entityManager.merge(userLogin);
                     userLogin.setLogoutDate(new java.util.Date());
                    
                     entityManager.persist(userLogin);
                    
                     System.out.println("Logout de " + userLogin.getUser().getLogin());
                     }
                     }
                    }


                    Check that I had to create it as a Stateless bean because of the EntityManager.

                    Regards,
                    Ricardo