1

I am creating a movie rental application using JSF 2.0 with Primefaces 3.4.1 as frontend. After a user is successfully registered, I need to automatically login with the newly created ID and redirect to the home page.

Currently, I am doing this way:

@ManagedBean
@ViewScoped
public class RegistrationBean extends BaseBean implements Serializable
{
   ...

   public String register() 
   {
      String nextPage = null;
      User userDetails = new User();

      try 
      {
         BeanUtils.copyProperties(userDetails, this);
         int registrationID = getServiceLocator().getUserService().registerUser(userDetails);
         LOGGER.info("Registered user successfully. Registration ID - {}", registrationID);

         // auto login
         LoginBean loginBean = (LoginBean)FacesUtils.getManagedBean("loginBean");
         loginBean.setUserId(userID);
         loginBean.setPassword(password);
         loginBean.login();
      }
      catch (Exception e) {
         LOGGER.error("Error during registration - " + e.getMessage());
         FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR, null, 
                  FacesUtils.getValueFromResource(RESOURCE_BUNDLE, REGISTRATION_FAIL));
         FacesContext.getCurrentInstance().addMessage(null, message);
      }
      return nextPage;
   }
}

LoginBean :

@ManagedBean
@SessionScoped
public class LoginBean extends BaseBean implements Serializable
{
   ...

   public String login() 
   {
      FacesContext ctx = FacesContext.getCurrentInstance();

      try 
      {
         currentUser = getServiceLocator().getUserService().findUser(userID);

         if (currentUser == null) 
         {
            ctx.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, null, 
                     FacesUtils.getValueFromResource(RESOURCE_BUNDLE, UNKNOWN_LOGIN)));
            return (userID = password = null);
         }
         else 
         {
            if (EncryptionUtils.compareHash(password, currentUser.getEncrPass())) {
               return INDEX + "?faces-redirect=true";
            }
            else 
            {
               ctx.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, null, 
                        FacesUtils.getValueFromResource(RESOURCE_BUNDLE, AUTH_FAIL)));
               return null;
            }
         }
      }
      catch (Exception e) 
      {
         final String errorMessage = "Error occured during login - " + e.getMessage();
         LOGGER.error(errorMessage);
         ctx.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, null, errorMessage));
      }

      return null;
   }
}

Above approach in register() method is, no doubt, wrong and insecure. Is there any way I can achieve the same in a cleaner way ??


Implementation using f:viewParam

RegistrationBean

int registrationID = getServiceLocator().getUserService().registerUser(userDetails);
LOGGER.info("Registered user successfully. Registration ID - {}", registrationID);
nextPage = LOGIN + "?faces-redirect=true&id=" + registrationID;

login.xhtml

<f:metadata>
   <f:viewParam name="id" value="#{loginBean.regID}" />
   <f:event listener="#{loginBean.autoLogin}" type="preRenderView"></f:event>
</f:metadata>

LoginBean

private int regID;

...

public void autoLogin()
{
   if (regID > 0 && !FacesContext.getCurrentInstance().isPostback())
   {
      currentUser = getServiceLocator().getUserService().findUser(regID);
      NavigationHandler navHandler = FacesUtils.getApplication().getNavigationHandler();
      navHandler.handleNavigation(FacesContext.getCurrentInstance(), null, INDEX + "?faces-redirect=true");
   }
}
Community
  • 1
  • 1
Vrushank
  • 2,763
  • 3
  • 27
  • 41

1 Answers1

0

So let us assume you are having three pages

  1. Register/User Signup
  2. Login
  3. Home page

Here successful registration need auto login and needs to be redirected to home page but usually manual login is must after registration.

Anyhow, I would suggest you to separate login credential check in separate method in a facade class or you can have it in LoginBean too.

public User doLogin(String userName, String password) {
     // query user
     // match with password
     // return null if not found or not matched
}

Add navigation-rule in faces-config.xml for registration bean and login bean

 <navigation-case>
        <from-outcome>loginSuccess</from-outcome>
        <to-view-id>/home.xhtml</to-view-id>
        <redirect/>
 </navigation-case>

In both registration bean and login bean call doLogin method then if user found set navigation

NavigationHandler nh = facesContext.getApplication().getNavigationHandler();
nh.handleNavigation(facesContext, null, "loginSuccess");
vels4j
  • 11,208
  • 5
  • 38
  • 63
  • Thanks for the reply. But is there any way, that I can forward the call to the `login()` method in LoginBean since `doLogin()` does the same thing. – Vrushank Jan 01 '13 at 08:41
  • yes you can do that. forward registration page to login page with param then in login bean param found in request, process it. – vels4j Jan 01 '13 at 08:51
  • I was able to implement your suggestion using with preRenderView event listener. I am updating my post to reflect the same. Thanks for the suggestion. Please let me know if you can suggest any improvements to my implementation. – Vrushank Jan 01 '13 at 10:49