6 Replies Latest reply on Apr 16, 2007 5:56 PM by shane.bryzak

    Seam Security: isUserInRole() expression

    jeffconstantin

      What is required to use isUserInRole() to control component rendering as follows:

      rendered="#{isUserInRole['admin']}"


      Any help is very much appreciated.

      This check is always returning false even though I am sure the user has the "admin" role. At least I can see the role being added to the Identity bean in my Authenticator bean.
      System.out.println("User: " + Identity.instance().getUsername() + " Adding Role: " + userRole.getRole());
      Identity.instance().addRole(userRole.getRole());
      


      Output From my Authenticator bean:
      15:26:32,301 INFO [STDOUT] User: constant Adding Role: admin
      15:26:32,301 INFO [STDOUT] User: constant Adding Role: user
      



      I think the authenticator.authenticate is working properly because I can use the rendered="#{identity.loggedIn}" successfully. However, I cannot get the isUserInRole() function to work.

      My Environment:
      1. jboss-seam-1.2.1.GA
      2. jboss-4.0.5.GA AS with EJB3 profile
      3. Seam Security "simplified mode" - this mode supports authentication services and simple role-based security checks.

      Components.xml
      <?xml version="1.0" encoding="utf-8"?>
      <components xmlns="http://jboss.com/products/seam/components"
       xmlns:core="http://jboss.com/products/seam/core"
       xmlns:security="http://jboss.com/products/seam/security"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:framework="http://jboss.com/products/seam/framework"
       xsi:schemaLocation=
       "http://jboss.com/products/seam/core http://jboss.com/products/seam/core-1.2.xsd
       http://jboss.com/products/seam/components http://jboss.com/products/seam/components-1.2.xsd
       http://jboss.com/products/seam/drools http://jboss.com/products/seam/drools-1.2.xsd
       http://jboss.com/products/seam/security http://jboss.com/products/seam/security-1.2.xsd">
      
       <security:identity authenticate-method="#{authenticator.authenticate}"/>
      
       <component name="org.jboss.seam.core.init">
       <property name="myFacesLifecycleBug">true</property>
       <property name="jndiPattern">seamapp/#{ejbName}/local</property>
       </component>
       <component name="entityManager" class="org.jboss.seam.core.ManagedPersistenceContext">
       <property name="persistenceUnitJndiName">java:/seamappEntityManagerFactory</property>
       </component>
      
       <!-- this will create the ejb objects for the selectItems -->
       <framework:entity-query name="colors" ejbql="select d from EdmColors d" />
       <framework:entity-query name="cars" ejbql="select d from EdmCars d" />
       <framework:entity-query name="yesnos" ejbql="select d from EdmBoolean d" />
      
      </components>
      


      Authenticator Bean
      package com.cox.edm;
      
      import java.util.List;
      
      import javax.ejb.Stateless;
      import javax.persistence.EntityManager;
      import javax.persistence.NoResultException;
      import javax.persistence.Query;
      
      import org.jboss.seam.annotations.In;
      import org.jboss.seam.annotations.Name;
      import org.jboss.seam.core.FacesMessages;
      import org.jboss.seam.security.Identity;
      
      @Name("authenticator")
      public class Authenticator {
      
       @In(create = true)
       private EntityManager entityManager;
      
       public boolean authenticate() {
       try
       {
       Query query = entityManager.createQuery("from EdmUsers where user_id = :userid and password = :password");
       query.setParameter("userid", Identity.instance().getUsername());
       query.setParameter("password", Identity.instance().getPassword());
       EdmUsers user = (EdmUsers) query.getSingleResult();
      
       query = entityManager.createQuery( "from EdmUserRoles where user_id = :userid ");
       query.setParameter("userid", Identity.instance().getUsername() );
       List<EdmUserRoles> list = (List<EdmUserRoles>)query.getResultList();
      
       if (list != null)
       {
       for (EdmUserRoles userRole : list){
       System.out.println("User: " + Identity.instance().getUsername() + " Adding Role: " + userRole.getRole());
       Identity.instance().addRole(userRole.getRole());
       }
       }
      
       return true;
       }
       catch (NoResultException ex)
       {
       FacesMessages.instance().add("Invalid username/password");
       return false;
       }
      
       }
      
      }


      My Logon.jsp
      <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
      <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
      <%@ taglib uri="http://jboss.com/products/seam/taglib" prefix="s" %>
      <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
      <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
      <f:view>
      <f:loadBundle basename="messages" var="msg"/>
       <head>
       <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
       <title><h:outputText value="#{msg.Application} #{msg.LoginTitle}"/></title>
       <style type="text/css" media="all">
       @import "style/default/screen.css";
       </style>
       </head>
       <body>
      
       <h1><h:outputText value="#{msg.Application} #{msg.Authentication}"/></h1>
      
       <h:form>
      
       <!-- ADD THE MENU SWITCHER -->
       <%@ include file="/menu.jsp" %>
      
       <div class="rvgFind" >
       <fieldset class="rvgFieldSet" >
       <legend><h:outputText value="#{msg.Authentication} Form"/></legend>
      
       <span class="rvgInputs">
       <h:outputLabel value="#{msg.Username}" for="username">
       <h:inputText value="#{identity.username}" id="username"/>
       </h:outputLabel>
       <h:outputLabel value="#{msg.Password}" for="password">
       <h:inputSecret redisplay="false" value="#{identity.password}" id="password"/>
       </h:outputLabel>
       </span>
      
       <span class="rvgActions">
       <h:commandButton type="submit" value="#{msg.Login}" action="#{identity.login}" rendered="#{not identity.loggedIn}"/>
       <h:commandButton type="submit" value="#{msg.Logout}" action="#{identity.logout}" rendered="#{identity.loggedIn}"/>
       </span>
      
       </fieldset>
       </div>
      
       </h:form>
      
      
       </body>
      </f:view>
      </html>
      



        • 1. Re: Seam Security: isUserInRole() expression
          shane.bryzak

          Use s:hasRole('admin') instead. isUserInRole is a servlet feature, and isn't currently integrated with Seam security.

          • 2. Re: Seam Security: isUserInRole() expression
            jeffconstantin

            Thanks Shane,

            I know this is a configuration issue, either a wrong version of a jar file for something. It should be simple but it is driving me nuts. Do you know of a working example that uses s:hasRole?

            I tried s:hasRole('admin') as follows and it throws the following exception when I hit that page. Is it using the same Seam taglib or do I have to add a new taglib?

            <h:selectOneMenu value="#{switcher.conversationIdOrOutcome}" rendered="#{s:hasRole('admin')}" >
            


            10:13:42,030 ERROR [[jsp]] Servlet.service() for servlet jsp threw exception
            javax.faces.el.EvaluationException: Cannot get value for expression '#{s:hasRole('admin')}'
             at org.apache.myfaces.el.ValueBindingImpl.getValue(ValueBindingImpl.java:402)
             at javax.faces.component.UIComponentBase.isRendered(UIComponentBase.java:1075)
             at javax.faces.webapp.UIComponentTag.isSuppressed(UIComponentTag.java:884)
             at javax.faces.webapp.UIComponentTag.doStartTag(UIComponentTag.java:313)
             at org.apache.jsp.logon_jsp._jspx_meth_h_selectOneMenu_0(logon_jsp.java:311)
             at org.apache.jsp.logon_jsp._jspx_meth_h_form_0(logon_jsp.java:245)
             at org.apache.jsp.logon_jsp._jspx_meth_f_view_0(logon_jsp.java:152)
             at org.apache.jsp.logon_jsp._jspService(logon_jsp.java:97)
             at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:97)
             at javax.servlet.http.HttpServlet.service(HttpServlet.java:810)
             at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:334)
             at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:314)
             at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:264)
             at javax.servlet.http.HttpServlet.service(HttpServlet.java:810)
             at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:252)
             at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
             at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:672)
             at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:463)
             at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:398)
             at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:301)
             at org.apache.myfaces.context.servlet.ServletExternalContextImpl.dispatch(ServletExternalContextImpl.java:416)
             at org.apache.myfaces.application.jsp.JspViewHandlerImpl.renderView(JspViewHandlerImpl.java:234)
             at org.jboss.seam.jsf.SeamViewHandler.renderView(SeamViewHandler.java:59)
             at org.apache.myfaces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:384)
             at javax.faces.webapp.FacesServlet.service(FacesServlet.java:138)
             at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:252)
             at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
             at org.jboss.seam.web.ExceptionFilter.doFilter(ExceptionFilter.java:57)
             at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
             at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
             at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)
             at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
             at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
             at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
             at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:178)
             at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:175)
             at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:74)
             at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:126)
             at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:105)
             at org.jboss.web.tomcat.tc5.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:156)
             at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:107)
             at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:148)
             at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:869)
             at org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Http11BaseProtocol.java:664)
             at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:527)
             at org.apache.tomcat.util.net.MasterSlaveWorkerThread.run(MasterSlaveWorkerThread.java:112)
             at java.lang.Thread.run(Thread.java:595)
            Caused by: javax.faces.el.ReferenceSyntaxException: Functions not supported in expressions. Function: s:hasRole
             at org.apache.myfaces.el.ValueBindingImpl$1.resolveFunction(ValueBindingImpl.java:71)
             at org.apache.commons.el.FunctionInvocation.evaluate(FunctionInvocation.java:148)
             at org.apache.myfaces.el.ValueBindingImpl.getValue(ValueBindingImpl.java:383)
             ... 46 more
            


            The documentation states that I have to use the following view-handler for this to work. If I add the component as follows to the the faces-config.xml file the pages will not load period.
            <application>
             <view-handler>org.jboss.seam.ui.facelet.SeamFaceletViewHandler</view-handler>
             </application>
            
            



            Exception (Is this using the wrong view-handler?):
            10:33:44,612 ERROR [STDERR] Apr 11, 2007 10:33:44 AM com.sun.facelets.FaceletViewHandler handleRenderException
            SEVERE: Error Rendering View[/logon.jsp]
            com.sun.facelets.FaceletException: Error Parsing /logon.jsp: Error Traced[line: 4] The content of elements must consist of well-formed character data or markup.
             at com.sun.facelets.compiler.SAXCompiler.doCompile(SAXCompiler.java:234)
             at com.sun.facelets.compiler.Compiler.compile(Compiler.java:105)
             at com.sun.facelets.impl.DefaultFaceletFactory.createFacelet(DefaultFaceletFactory.java:197)
             at com.sun.facelets.impl.DefaultFaceletFactory.getFacelet(DefaultFaceletFactory.java:144)
             at com.sun.facelets.impl.DefaultFaceletFactory.getFacelet(DefaultFaceletFactory.java:95)
             at com.sun.facelets.FaceletViewHandler.buildView(FaceletViewHandler.java:496)
             at com.sun.facelets.FaceletViewHandler.renderView(FaceletViewHandler.java:546)
             at org.apache.myfaces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:384)
             at javax.faces.webapp.FacesServlet.service(FacesServlet.java:138)
             at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:252)
             at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
             at org.jboss.seam.web.ExceptionFilter.doFilter(ExceptionFilter.java:57)
             at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
             at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
             at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)
             at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
             at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
             at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
             at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:178)
             at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:175)
             at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:74)
             at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:126)
             at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:105)
             at org.jboss.web.tomcat.tc5.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:156)
             at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:107)
             at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:148)
             at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:869)
             at org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Http11BaseProtocol.java:664)
             at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:527)
             at org.apache.tomcat.util.net.MasterSlaveWorkerThread.run(MasterSlaveWorkerThread.java:112)
             at java.lang.Thread.run(Thread.java:595)
            


            My Logon.jsp page:
            <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
            <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
            
            <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
            <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
            <%@ taglib uri="http://jboss.com/products/seam/taglib" prefix="s" %>
            
            <f:view>
            <f:loadBundle basename="messages" var="msg"/>
             <head>
             <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
             <title><h:outputText value="#{msg.Application} #{msg.LoginTitle}"/></title>
             <style type="text/css" media="all">
             @import "style/default/screen.css";
             </style>
             </head>
             <body>
            
             <h1><h:outputText value="#{msg.Application} #{msg.Authentication}"/></h1>
            
             <h:form>
            
             <div class="rvgSwitch" rendered="#{identity.loggedIn}" >
             <h:selectOneMenu value="#{switcher.conversationIdOrOutcome}" rendered="#{s:hasRole('admin')}" >
             <f:selectItem itemLabel="#{msg.createUser}" itemValue="editEdmUsers" />
             <f:selectItem itemLabel="#{msg.createRole}" itemValue="editEdmRoles" />
             <f:selectItem itemLabel="#{msg.createUserRole}" itemValue="editEdmUserRoles" />
             <f:selectItem itemLabel="#{msg.createBoolean}" itemValue="editEdmBoolean" />
             <f:selectItem itemLabel="#{msg.createMaster}" itemValue="editEdmMaster" />
             <f:selectItem itemLabel="#{msg.createColor}" itemValue="editEdmColors" />
             <f:selectItem itemLabel="#{msg.createCar}" itemValue="editEdmCars" />
             <f:selectItem itemLabel="#{msg.findUser}" itemValue="findEdmUsers" />
             <f:selectItem itemLabel="#{msg.findRole}" itemValue="findEdmRoles" />
             <f:selectItem itemLabel="#{msg.findUserRole}" itemValue="findEdmUserRoles" />
             <f:selectItem itemLabel="#{msg.findBoolean}" itemValue="findEdmBoolean" />
             <f:selectItem itemLabel="#{msg.findMaster}" itemValue="findEdmMaster" />
             <f:selectItem itemLabel="#{msg.findColor}" itemValue="findEdmColors" />
             <f:selectItem itemLabel="#{msg.findCar}" itemValue="findEdmCars" />
             <f:selectItems value="#{switcher.selectItems}"/>
             </h:selectOneMenu>
             <h:selectOneMenu value="#{switcher.conversationIdOrOutcome}" rendered="#{not s:hasRole('admin')}" >
             <f:selectItem itemLabel="#{msg.createMaster}" itemValue="editEdmMaster" />
             <f:selectItem itemLabel="#{msg.findMaster}" itemValue="findEdmMaster" />
             <f:selectItems value="#{switcher.selectItems}"/>
             </h:selectOneMenu>
             <h:commandButton action="#{switcher.select}" value="Switch" rendered="#{identity.loggedIn}"/>
             </div>
            
             <div class="rvgFind" >
             <fieldset class="rvgFieldSet" >
             <legend><h:outputText value="#{msg.Authentication} Form"/></legend>
            
             <span class="rvgInputs">
             <h:outputLabel value="#{msg.Username}" for="username">
             <h:inputText value="#{identity.username}" id="username"/>
             </h:outputLabel>
             <h:outputLabel value="#{msg.Password}" for="password">
             <h:inputSecret redisplay="false" value="#{identity.password}" id="password"/>
             </h:outputLabel>
             </span>
            
             <span class="rvgActions">
             <h:commandButton type="submit" value="#{msg.Login}" action="#{identity.login}" rendered="#{not identity.loggedIn}"/>
             <h:commandButton type="submit" value="#{msg.Logout}" action="#{identity.logout}" rendered="#{identity.loggedIn}"/>
             </span>
            
             </fieldset>
             </div>
            
             </h:form>
            
             </body>
             </f:view>
            </html>
            


            • 3. Re: Seam Security: isUserInRole() expression
              jeffconstantin

              Shane,

              This is working. The problem was with the SeamFaceletViewHandler. It is required to do the Seam Security using s:hasRole('admin'). That was documented. It appears to require a different format for the JSP pages as follows: ( it likes the <jsp:root format )

              <?xml version="1.0"?>
              <jsp:root xmlns:jsp="http://java.sun.com/JSP/Page"
               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="http://www.w3.org/1999/xhtml"
               version="2.0">
               <jsp:output doctype-root-element="html"
               doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN"
               doctype-system="http://www.w3c.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"/>
               <jsp:directive.page contentType="text/html"/>
               <html>
              


              previously it was:
              <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
              <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
              <%@ taglib uri="http://jboss.com/products/seam/taglib" prefix="s" %>
              <%@ taglib uri="http://jboss.com/products/seam/entityconverter/taglib" prefix="ec"%>
              
              <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
              <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
              



              • 4. Re: Seam Security: isUserInRole() expression
                james_hays

                So, this documentation in Seam is wrong?

                http://docs.jboss.com/seam/1.2.1.GA/reference/en/html/components.html


                org.jboss.seam.core.isUserInRole

                Allows JSF pages to choose to render a control, depending upon the roles available to the current principal. <h:commandButton value="edit" rendered="#{isUserInRole['admin']}"/>.



                • 5. Re: Seam Security: isUserInRole() expression
                  jeffconstantin

                  From my experience (and from this posting) this code does not work on the frontend. The documentation is incorrect.

                  Allows JSF pages to choose to render a control, depending upon the roles available to the current principal. <h:commandButton value="edit" rendered="#{isUserInRole['admin']}"/>.

                  you have to use (this does works)
                  rendered="#{s:hasRole('admin')}"


                  • 6. Re: Seam Security: isUserInRole() expression
                    shane.bryzak

                     

                    "james_hays@mac.com" wrote:
                    So, this documentation in Seam is wrong?

                    http://docs.jboss.com/seam/1.2.1.GA/reference/en/html/components.html


                    The isUserInRole that was originally built into Seam is based on servlet security (and still is). In this regard the documentation is technically correct, however if you are using Seam security then you have to use s:hasRole.