Search code examples
sessionjsf-2

JSF AJAX and normal redirect to login and back to previous page


Current status :

If any session time out occurs, redirectToLogin function in FacesAjaxAwareUserFilter will be executed. From there I can redirect to any page I need. I get the URI in all cases. It's all working fine and big thanks to BalusC. :)

Now the second part which makes the issue

Redirect to login and come back to the previous page.

For Eg :

Page 5----> Login------> Page 5

I have appended the redirect URI to the login URI and retrieved the values from the bean.

But the problem is that I have 2 pages before the user login. A login mode selection page (ie; google authentication or default login) and the page that reads the username and password.

How can I pass the redirect URI through both the pages.?

This is the code I have used to redirect at Ajax time out and in normal session time out.

Class FacesAjaxAwareUserFilter

   if ("partial/ajax".equals(request.getHeader("Faces-Request"))) {
                res.setContentType("text/xml");
                res.setCharacterEncoding("UTF-8");
                res.getWriter().printf(FACES_REDIRECT_XML, request.getContextPath() + getLoginUrl()+"?redirectUrlPattern="+request.getRequestURI());
            }
            else {
                if (request.getRequestedSessionId()!=null && (!SecurityUtils.getSubject().isAuthenticated() || !request.isRequestedSessionIdValid())) {
                    response.sendRedirect(getLoginUrl()+"?redirectUrlPattern="+request.getRequestURI());
                    return; 
                }
                super.redirectToLogin(req, res);
            }

Method used is FullAjaxExceptionHandlerFactory in Omniface.

I have used a method of appending the values to the URI, but it fails to identify whether the session is expired or a session not created (when a user logs in at first).

Problem Code

if (request.getRequestedSessionId()!=null && (!SecurityUtils.getSubject().isAuthenticated() || !request.isRequestedSessionIdValid())) 

I am looking for a way to identify the expired session from new session created before login.

Wish to implement this in a Better Way.

A method which will not append present URI with the redirect URL is most welcomed.


Solution

  • I have founded out a solution but still i don't find it as the best solution. Any other answer for doing it is greatly appreciated.

    Step 1

    Configure the application to detect Ajax Timeout and normal timeout. This is how i did it..!!

    Step 2

    Finding the URI when session timeout occurs, using this.

    FacesAjaxAwareUserFilter will grab the ServletRequest and ServletResponse for you. form that you can convert that to HttpServletRequest and HttpServletResponse using this

            HttpServletRequest request = (HttpServletRequest) req;
            HttpServletResponse response= (HttpServletResponse) res; 
    

    The request.getRequestURI() will get you the redirect URI

        String redirectURI=request.getRequestURI();
    

    Now you want to save this to some storage so that you can use it in any place you want. The only way i found is to append it with URL using this.

    res.getWriter().printf(FACES_REDIRECT_XML, request.getContextPath() + "/sessionexpired"+"?redirectUrlPattern="+request.getRequestURI());
    

    or

    response.sendRedirect("/sessionexpired"+"?redirectUrlPattern="+request.getRequestURI());
    

    Now on the page load of my sessionExpiry page bean, i used this to grab the value passed through the URL

    redirectUrl=FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("redirectUrlPattern");
    

    Now using JavaScript i set that value of redirectUrl to localStorage. This is how you can save values to local storage.

    This is my sessionexpiry.xhtml page.

    <script type="text/javascript">
    function setRedirectURIToLocalStorage(){
        if(typeof(Storage)!=="undefined")
          {
            localStorage.redirectURI=document.getElementById("redirectUrl").value;
            window.location.href="/login";
          }
    }
    </script>
    </h:head>
    <h:body id="body" onload="setRedirectURIToLocalStorage()">
        <f:view contentType="text/html">
    <h:form prependId="false" >  
    <h:inputHidden id="redirectUrl" value="#{sessionExpBean.redirectUrl}" />
    <h:outputText value="Session Expired... Redirecting...!!"></h:outputText>
    </h:form>
        </f:view>
    </h:body>
    

    The page will call setRedirectURIToLocalStorage() function onLoad and then it set the values to the localStorage. Thus the redirect value is available all across the browser. You can use that in any page you need.!! All you need to do is to check in this variable localStorage.redirectURI