4 Replies Latest reply on Jul 15, 2010 2:56 PM by nbelaevski

    Richfaces and expired session redirect - JAAS

    tmccobb

      Container:  JBoss 4.22, FORM based authentication against JAAS LDAP login context

      JSF 1.2; Richfaces 3.3.2 SR1

      MyFaces 1.2.6


      Trying to configure a redirect to a login page when the session expires.  Actually, the container handles this without doing anything.  As soon as the session expires, the app redirects to the login page.  The problem is that after reauthentication the request is looking for saved state from the expired session and throws


      javax.faces.application.ViewExpiredException: /Summary.facesNo saved view state could be found for the view identifier: 

       

      It seems that this container mechanism trumps everything:  PhaseListeners, Servlet Filters, and javascript, 
      specifically the A4J.AJAX.onExpired(...) call, which never gets fired.  A simple solution that I found was
      adding this to web.xml:


      <error-page>
              <exception-type>javax.faces.application.ViewExpiredException</exception-type>
              <location>/SessionError.jsp</location>
      </error-page>

      I have even tried this with the RedrectFilter suggested at http://wiki.apache.org/myfaces/Handling_Server_Errors

      <error-page>
              <exception-type>javax.faces.application.ViewExpiredException</exception-type>
              <location>/redirect?url=/SessionError.jsp</location>
      </error-page>

      In either case, the container is forcing re-authentication first, and THEN redirecting to .SessionError.jsp.

      I was hoping that somehow the Richfaces org.ajax4jsf.handleViewExpiredOnClient would give me some options, but when
      implemented, as I said, the javascript is never fired and after re-authentication, the app hangs on a blank screen.

      In web.xml the Richfaces handler is implemented thus:

       

           //Turned off Myfaces error handling per JIRA notes
           <context-param>
              <param-name>org.apache.myfaces.ERROR_HANDLING</param-name>
              <param-value>false</param-value>
            </context-param>
             
            <context-param>
              <param-name>org.ajax4jsf.handleViewExpiredOnClient</param-name>
              <param-value>true</param-value>
           </context-param>   

      I do have a HttpSessionListener implemented where I can unfailingly catch the expiring session event.  Is there 
      something I can do with the session attributes org.ajax4jsf.application.AjaxStateHolder or
      org.ajax4jsf.application.AjaxStateManager.view_sequence in the expiring session that will avoid the
      javax.faces.application.ViewExpiredException?

      I am using <a4j:poll interval="[5 sec after session timeout]" reRender="someComponent"/> to detect the expired session.
        • 1. Re: Richfaces and expired session redirect - JAAS
          tmccobb

          If I forego the redirect to the SessionError.jsp page (which has a message announcing the session timeout and buttons to log in again or quit) and just redirect to a "home" page in the application then at least I get back into the application.  Otherwise it would non-sensically require login and then go to the error page.

           

          The ViewExpiredException error is still thrown however.  Not pretty, but it at least it goes back into the app.

           

          BTW, I tried the custom ViewHandler solution at http://www.gregbugaj.com/?p=164 without success.

           

          Also tried adding

           

          <context-param>
                <param-name>com.sun.faces.enableRestoreView11Compatibility</param-name>
                <param-value>true</param-value>
          </context-param>

           

          Did not work either.

          • 2. Re: Richfaces and expired session redirect - JAAS
            nbelaevski
            I was hoping that somehow the Richfaces org.ajax4jsf.handleViewExpiredOnClient would give me some options, but when
            implemented, as I said, the javascript is never fired and after re-authentication, the app hangs on a blank screen.

            handleViewExpiredOnClient is handled by RF filter, and in the case of JAAS authorization, it isn't invoked at all.

             

            <context-param>
                  <param-name>com.sun.faces.enableRestoreView11Compatibility</param-name>
                  <param-value>true</param-value>
            </context-param>

            You are using MyFaces, so parameter name should be different: https://issues.apache.org/jira/browse/MYFACES-2452 (note 1.2.8 MyFaces version).

             

            Can you please check this solution: http://roneiv.wordpress.com/2008/02/18/jaas-authentication-mechanism-is-it-possible-to-force-j_security_check-to-go-to-a-specific-page/ ? It uses redirect, so submitted view data should not be processed and view not restored.

            • 3. Re: Richfaces and expired session redirect - JAAS
              tmccobb

              Nick, thanks for the reply.  I will be trying the Login servlet idea later today.  Having looked at it I still have a question of whether the servlet will even get reached before JAAS goes back to the login page, since JAAS seems ot trample on everything else until authenticated.  But I will see.

               

              I tried a purely javascript solution, which I actually like better from a design standpoint, because I can throw up a modal form and never leave the screen the user was on - I don't really need to worry about restoring the view.  I put a simple javascript countdown timer that is initiated and refreshed with the page onLoad():

               

              var elapsedTime = 0;

              //could use an arbitrary value here and ignore container timeout altogether

              var maxTime = (<%=session.getMaxInactiveInterval()%> )-180;
              var oneSecond;
              oneSecond = window.setTimeout("timeoutCheck();",1000);
              function timeoutCheck() {
                   elapsedTime = elapsedTime + 1;
                   if (elapsedTime > maxTime) {
                     Richfaces.showModalPanel('mpTimeout');
                    }
                else {
                  oneSecond = window.setTimeout("timeoutCheck();",1000);
                 //window.status = "Session will time out in: " + (maxTime - elapsedTime);
                }

              }

               

              Then in page there is <htm:body onload="timeoutCheck();">

               

              Of course, the issue with this is that the page is not reloaded with an Ajax request, which is the point of Richfaces.  So I am considering strategies for refreshing the javascript time on ajax requests, obviously wanting to avoid numerous editing on a component by component basis.  How about wrapping a page in a <a4j:status /> tag and calling the timer from the onstart() or onstop() events?

              • 4. Re: Richfaces and expired session redirect - JAAS
                nbelaevski

                There's undocumented A4J.AJAX.AddListener function that can be used to register listener called for each AJAX request. Another option can be a4j:queue tag.