3 Replies Latest reply on Aug 17, 2007 10:04 AM by steve tynor

    conditional redirect on exception - how?

    steve tynor Novice

      My application requires two-stage authentication. I must "login", but after logging in, the user must choose a "client" and is not permitted to access any of the rest of the application until she/he does so. I've managed to restrict access to my pages with EL expressions, for example:

       <page view-id="/home.xhtml">
       <restrict>#{(not empty authenticator.currentClient)}</restrict>
       </page>
      


      and have added navigation rules on my login.page.xml to redirect to a page to set this value if the login process itself does not set it:

       <navigation from-action="#{identity.login}">
       <rule if="#{identity.loggedIn and (empty currentClient)}">
       <redirect view-id="/ChooseClient.xhtml"/>
       </rule>
       <rule if="#{identity.loggedIn and (not empty currentClient)}">
       <redirect view-id="/home.xhtml"/>
       </rule>
       </navigation>
      


      So far so good -- I am directed to the ChooseClient page at the proper times, and if I attempt to access a protected page before setting the currentClient (e.g. via a bookmark or manually typing a url), I get the desired AuthorizationException. However, what I want to happen is on attempt to access a restricted page, redirect to the ChooseClient page if the restriction was because the client wasn't choosen (as opposed to simply not having the proper role).

      I've tried adding an EL expression on the redirect in pages.xml:

       <exception class="org.jboss.seam.security.AuthorizationException">
       <redirect view-id="#{(empty authenticator.currentClient) ? '/ChooseClient.xhtml' : '/error.xhtml'}">
       <message>You don't have permission to do this</message>
       </redirect>
       </exception>
      


      Unfortunately, that doesn't work - when I trigger the exception, JSF pukes:

      20:23:55,256 FATAL [application] JSF1010: Illegal view ID #{(empty authenticator.currentClient) ? '/ChooseClient.xhtml' : '/error.xhtml'}. The ID must begin with '/'


      So I tried unconditionally redirecting to a facelet that redirects:
      <!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:c="http://java.sun.com/jstl/core"
       xmlns:ui="http://java.sun.com/jsf/facelets"
       template="/WEB-INF/facelets/templates/template.xhtml">
      
      <c:choose>
      <c:when test="#{empty authenticator.currentClient}">
       <c:redirect url="/ChooseClient.xhtml"/>
      </c:when>
      <c:otherwise>
       <c:redirect url="/error.xhtml"/>
      </c:otherwise>
      </c:choose>
      
      </ui:composition>


      But that fails with a facelet compiler error(!?) saying:

      /maybeChooseClient.xhtml @16,41 <c:redirect> Tag Library supports namespace: http://java.sun.com/jstl/core, but no tag was defined for name: redirect
      


      (despite the fact that the facelet doc claims to implement the "core" JSTL library with only a few restrictions - not being mentioned.

      So... I can't find any way to conditionally redirect on exception. Ideas?

      JSF 1.2
      JBoss AS 4.2.1
      Seam 1.2.1-GA


        • 1. Re: conditional redirect on exception - how?
          Matt Drees Master

          Maybe something like this.

           <exception class="org.jboss.seam.security.AuthorizationException">
           <redirect view-id="/handleAuthorizationException.xhtml">
           <message>You don't have permission to do this</message>
           </redirect>
           </exception>
          

          and in pages.xml
          <page view-id="/handleAuthorizationException.xhtml">
           <action if="#{empty authenticator.currentClient}" execute="/ChooseClient.xhtml"/>
           <action if="#{not empty authenticator.currentClient}" execute="/error.xhtml"/>
          </page>
          


          I haven't tested it, but I'm pretty sure that'd work.

          However, you may want to put a feature request in Jira for value expressions in the view-id attribute of ExceptionHandlers (which would let your first approach work). I could see it being a useful thing.

          • 2. Re: conditional redirect on exception - how?
            steve tynor Novice

            Thanks Matt!

            That works. And it turns out that EL _is_ evaluated in the message, so i can generate two different messages depending on the cause of the exception:

            <exception class="org.jboss.seam.security.AuthorizationException">
             <redirect view-id="/handleAuthorizationException.xhtml">
             <message>#{(empty authenticator.currentClient) ? 'You must select a client before accessing any other pages' : 'You don't have permission to do this'}</message>
             </redirect>
             </exception>