3 Replies Latest reply on Apr 10, 2007 12:10 AM by Richard Leherpeur

    page action not called when login-required=

    Richard Leherpeur Novice

      hello,

      I try to achieve the following behavior. When a user want to see his account, he will be directed an account page that depends on certain user information.
      The account page is in the restricted area that requires login.
      So when the user click on a "View account" link, I'd like to go first to the login page and then have the accountAction.outcome method called (This methods return string representing the outcome).

      I have the following pages configuration

      <pages login-view-id="/public/login.xhtml">
      
       <page view-id="/restricted/*" login-required="true"/>
      
       <page view-id="/account.xhtml" action="#{accountAction.outcome}" login-required="true" />
      
      ...
      </pages>
      


      The user access the account page by clicking on the following link:

      <h:outputLink value="account.xhtml">View Account</h:outputLink>
      


      When clicking on that link, I get the login page, I can login properly but the action method is never called (so I don't go to the account page, but remain in the login page).
      If I remove the login-required attribute, then the action is called properly (of course, there is no login in that case).

      Is it possible to use both attributes "action" and "login-required" together?
      If not, what would be a way to achieve this behavior?

      Regards,

      Richard

        • 1. Re: page action not called when login-required=
          Shane Bryzak Master

          Please raise this in JIRA.

          • 2. Re: page action not called when login-required=
            Patrick Madden Newbie

            What version of Seam are you using. Are you using the new Identity and Authenticator paradigm?

            If so here is how I define pages that are required to have the user logged in and I successfully get redirected to the proper page when login is successful.

            Here is an snippet from my pages.xml:

             <page view-id="/download.xhtml">
             <restrict>#{s:hasRole('user')}</restrict>
             </page>
            
             <page view-id="/shop.xhtml">
             <restrict>#{s:hasRole('user')}</restrict>
             </page>
            


            Here is my Authenticator object which is generated by seam-gen and then edited by me.

            package com.clooster.web.ejb.session;
            
            import java.util.List;
            
            import javax.faces.application.FacesMessage;
            import javax.faces.context.FacesContext;
            import javax.naming.NamingException;
            import javax.persistence.EntityManager;
            import javax.persistence.EntityManagerFactory;
            
            import org.jboss.seam.annotations.In;
            import org.jboss.seam.annotations.Logger;
            import org.jboss.seam.annotations.Name;
            import org.jboss.seam.contexts.Context;
            import org.jboss.seam.core.FacesMessages;
            import org.jboss.seam.log.Log;
            import org.jboss.seam.security.Identity;
            import org.jboss.seam.util.Naming;
            
            import com.clooster.web.ejb.entity.ClUsers;
            import com.clooster.xjava.common.XSystem;
            
            @Name("authenticator")
            public class Authenticator
            {
             @Logger
             Log log;
            
             @In
             Identity identity;
            
             @In
             FacesMessages facesMessages;
            
             @In
             private transient Context sessionContext;
            
             @In
             private transient FacesContext facesContext;
            
             @SuppressWarnings("unchecked")
             public boolean authenticate()
             {
             boolean rc;
            
             log.info("authenticating #0", identity.getUsername());
            
             EntityManager em;
             try
             {
             em = this.getEntityManager();
            
             List<ClUsers> results = em
             .createQuery(
             "from ClUsers where cloosterid=:cloosterid and password=:password")
             .setParameter("cloosterid", identity.getUsername())
             .setParameter("password",
             identity.getPassword().getBytes())
             .getResultList();
            
             if (results.size() == 0)
             {
             facesContext.addMessage(null, new FacesMessage(
             "Invalid login"));
            
             rc = false;
             }
             else
             {
             ClUsers user = results.get(0);
            
             // log.info("Logged in user = " + user.getFirstname() +
             // " " + user.getLastname());
             sessionContext.set("loggedIn", true);
             sessionContext.set("user", user);
            
             // write your authentication logic here,
             // return true if the authentication was
             // successful, false otherwise
             identity.addRole("user");
            
             log.info("Logged In");
             rc = true;
             }
             }
             catch (NamingException e)
             {
             facesContext
             .addMessage(
             null,
             new FacesMessage(
             "Internal Error obtaining EntiryManager - contact webmaster@cloostr.com"));
            
             XSystem.logException(e);
            
             rc = false;
             }
            
             return rc;
             }
            
             protected EntityManager getEntityManager() throws NamingException
             {
             EntityManagerFactory factory = (EntityManagerFactory) Naming
             .getInitialContext().lookup(
             "java:/CloosterEntityManagerFactory");
            
             EntityManager em = factory.createEntityManager();
            
             return em;
             }
            }
            


            Here is my login.xhtml mainly generated via seam-gen as well:

            <!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
             "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
            <ui:composition xmlns="http://www.w3.org/1999/xhtml"
             xmlns:s="http://jboss.com/products/seam/taglib"
             xmlns:ui="http://java.sun.com/jsf/facelets"
             xmlns:f="http://java.sun.com/jsf/core"
             xmlns:h="http://java.sun.com/jsf/html"
             xmlns:rich="http://richfaces.ajax4jsf.org/rich"
             template="layout/template.xhtml">
            
            <ui:define name="body">
            
             <h:messages styleClass="message"/>
            
             <h:form id="login">
            
             <rich:panel>
             <f:facet name="header">Login</f:facet>
            
             <p>Please login using any username and password</p>
            
             <div class="dialog">
             <h:panelGrid columns="2" rowClasses="prop" columnClasses="name,value">
             <h:outputLabel for="username">Username</h:outputLabel>
             <h:inputText id="username"
             value="#{identity.username}"/>
             <h:outputLabel for="password">Password</h:outputLabel>
             <h:inputSecret id="password"
             value="#{identity.password}"/>
             <h:outputLabel for="rememberMe">Remember me</h:outputLabel>
             <h:selectBooleanCheckbox id="rememberMe"
             value="#{identity.rememberMe}"/>
             </h:panelGrid>
             </div>
            
             </rich:panel>
            
             <div class="actionButtons">
             <h:commandButton value="Login" action="#{identity.login}"/>
             </div>
            
             </h:form>
            
             </ui:define>
            </ui:composition>
            


            The identity object looks up the authenticator binding and calls the Authenticator.authenticate method.

            If your using older seam it may be good to just create an empty shell project and port the newer code into your old project.

            Its working for me without much hassel at all.

            The other option is to not even show the account link unless the user is currently logged in. Here is my menu.xhtml that is shown at the top of every page in my app:

            <rich:toolBar
             xmlns="http://www.w3.org/1999/xhtml"
             xmlns:ui="http://java.sun.com/jsf/facelets"
             xmlns:h="http://java.sun.com/jsf/html"
             xmlns:f="http://java.sun.com/jsf/core"
             xmlns:s="http://jboss.com/products/seam/taglib"
             xmlns:rich="http://richfaces.ajax4jsf.org/rich"
             xmlns:a="https://ajax4jsf.dev.java.net/ajax">
             <rich:toolBarGroup>
             <h:outputText value="Clooster"/>
             <s:link view="/home.xhtml" value="Home"/>
             <s:link view="/search.xhtml" value="Search"/>
             <s:link view="/searchApplet.xhtml" value="Search Applet"/>
             <s:link view="/headlines.xhtml" value="Headlines"/>
             <s:link view="/download.xhtml" value="Download"/>
             <s:link view="/shop.xhtml" value="Shop"/>
             </rich:toolBarGroup>
             <rich:toolBarGroup location="right">
             <a:status startText="In Progress" stopText="Ready"/>
             </rich:toolBarGroup>
             <rich:toolBarGroup itemSeparator="line" location="right">
             <h:outputText value="Welcome, #{user.firstname} #{user.lastname}" rendered="#{identity.loggedIn}"/>
             <s:link view="/myAccount.xhtml" value="My Account" rendered="#{identity.loggedIn}"/>
             <s:link view="/login.xhtml" value="Login" rendered="#{not identity.loggedIn}"/>
             <s:link view="/registerUser.xhtml" value="Create Account" rendered="#{not identity.loggedIn}"/>
             <s:link view="/home.xhtml" action="#{identity.logout}" value="Logout" rendered="#{identity.loggedIn}"/>
             </rich:toolBarGroup>
            </rich:toolBar>
            


            Here you can see when the user logs out it bring the user back to the home page. Also it won't render the "My Account" page until the user is logged in.

            Hope this helps,

            PVM

            • 3. Re: page action not called when login-required=
              Richard Leherpeur Novice

              yes, I use the Security framework (jboss-seam-1.2.1.GA) which works great
              except for that particular case.

              http://jira.jboss.org/jira/browse/JBSEAM-1157