10 Replies Latest reply: Apr 30, 2012 10:00 AM by ravi j RSS

RF4: Session timeout, how?

Sergio Samayoa Newbie

There is no more A4J.AJAX.onExpired so how to handle session timeout/expiration in RF4?

 

Regards.

 

FOLLOW UP:

Server sends login page with status 200 so AJAX doesnt known what to do, is not a redirect.

I will experiment with servlet and see if does the trick.

Regards.

 

FOLLOW UP:

We are toast!

response.sendRedirect() doesn't did the trick, AJAX simple take it as valid response.

How to trap AJAX request BEFORE RF's components?

Regards.

  • 1. Re: RF4: Session timeout, how?
    Sergio Samayoa Newbie

    After reading abot in the Web (it is a common problem) I found a solution, simple and somewhat elegant.

     

    First, this is my environment:

     

    1. Glassfish 3.1 (JSF 2.1.x /  Servlet 3.0)
    2. Richfaces 4.0
    3. Container managed secutiry

     

    When server receives a request and session is already expired it doesn't sends a redirect to login page, it sends the login page itself.

    JSF AJAX js code doesn't expect that, it expects an XML which may contain partial rendering information, error information or redirect informatiom.

    So, instead of setting login-form-page to a real page (JSF or HTML) I set to a servlet;

     

    <login-config>

      <auth-method>FORM</auth-method>

      <realm-name>planillagt</realm-name>

      <form-login-config>

       <form-login-page>/ingreso</form-login-page>

       <form-error-page>/ingreso</form-error-page>

      </form-login-config>

    </login-config>

     

    Which does the redirect to real login page:

     

    @WebServlet("/ingreso")

    public class Ingreso extends HttpServlet {

              private static final long serialVersionUID = 1L;

     

     

              protected void doGet(HttpServletRequest request,

                                  HttpServletResponse response) throws ServletException, IOException {

                        doService(request, response);

              }

     

     

              protected void doPost(HttpServletRequest request,

                                  HttpServletResponse response) throws ServletException, IOException {

                        doService(request, response);

              }

     

     

              protected void doService(HttpServletRequest request,

                                  HttpServletResponse response) throws ServletException, IOException {

                        String facesRequest = request.getHeader("Faces-Request");

                        if (facesRequest != null && facesRequest.equals("partial/ajax")) {

                                  String url = MessageFormat.format(

                                                      "{0}://{1}:{2,number,####0}{3}/ingreso.view",

                                                      request.getScheme(), request.getServerName(),

                                                      request.getServerPort(), request.getContextPath());

                                  PrintWriter pw = response.getWriter();

                                  pw.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");

                                  pw.println("<partial-response><redirect url=\"" + url

                                                      + "\"></redirect></partial-response>");

                                  pw.flush();

                        } else {

                                  response.sendRedirect(request.getContextPath() + "/ingreso.view");

                        }

              }

     

    }

     

    If servlet detects that request comes from JSF AJAX ("Faces-Request" containing "partial/ajax") responses the JSF's redirect XML else just redirects to real login page.

     

    This is working for me now, hope that works for you also.

     

    Regards.

  • 2. Re: RF4: Session timeout, how?
    jules poit Newbie

    Hey guys

     

    I implemented your solution - working like a charm But I noticed that on Firefox and Safari the header Faces-Request is not being send in the POST request !!

    It is working with Chrome/IE. So, there is no way to detect that it is a partial/ajax

     

    Do you any workaround for that ? Or any leads ?

     

    Thank you

  • 3. Re: RF4: Session timeout, how?
    Nick Belaevski Master

    Hi,

     

    I have this header sent from FF - are you checking AJAX request or common form submit?

  • 4. Re: RF4: Session timeout, how?
    jules poit Newbie

    Hi

     

    It does not matter apparently, I tried from a4j component (commandbutton) and also h:commandbutton.

    The result is the same, my Faces-Request value is null and when I look at Firebug I have that:

     

    ServerApache-Coyote/1.1
    Set-CookieJSESSIONID=3D172CE279A40EE22DAB034AF930F524; Path=/; Secure
    Locationhttps://localhost:8443/servlet/
    Content-Length0
    DateThu, 09 Jun 2011 21:30:39 GMT

    Request Headersview source

    Hostlocalhost:8443
    User-AgentMozilla/5.0 (Windows NT 5.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1
    Accepttext/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Languageen-us,en;q=0.5
    Accept-Encodinggzip, deflate
    Accept-CharsetISO-8859-1,utf-8;q=0.7,*;q=0.7
    Keep-Alive115
    Connectionkeep-alive
    Refererhttps://localhost:8443/settings/
    Cookie__utma=111872281.1694059113.1305215609.1307648008.1307654090.70; __utmz=111872281.1305215609.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); JSESSIONID=F4BEF48E826788A2E972A6EE3AC4A97B; __utmc=111872281; __utmb=111872281.14.10.1307654090

     

    And from an A4J action :

     

    Hostlocalhost:8443
    User-AgentMozilla/5.0 (Windows NT 5.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1
    Accepttext/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Languageen-us,en;q=0.5
    Accept-Encodinggzip, deflate
    Accept-CharsetISO-8859-1,utf-8;q=0.7,*;q=0.7
    Keep-Alive115
    Connectionkeep-alive
    Faces-Requestpartial/ajax
    Content-Typeapplication/x-www-form-urlencoded; charset=UTF-8
    Refererhttps://localhost:8443/aircraft/
    Content-Length1231
    Cookie__utma=111872281.1694059113.1305215609.1307648008.1307654090.70; __utmz=111872281.1305215609.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); JSESSIONID=213AF872F78920A6FC581E6B496D1E90; __utmc=111872281; __utmb=111872281.18.10.1307654090
    Pragmano-cache
    Cache-Controlno-cache

     

    But I am still having request.getHeader("Faces-Request") = null.

  • 5. Re: RF4: Session timeout, how?
    Florian Dupont Newbie

    I'm having the same issue, did you find a solution ?

  • 6. Re: RF4: Session timeout, how?
    jules poit Newbie

    I used a filter like that :

     

     

    public class SessionTimeoutFilter implements Filter {

     

        private final Log    logger        = LogFactory

                                                .getLog(SessionTimeoutFilter.class);

     

        private String        timeoutPage    = "YOUR URL";

     

        /*

         * (non-Jsdoc)

         * @see javax.servlet.Filter#init(javax.servlet.FilterConfig)

         */

        public void init(FilterConfig filterConfig) throws ServletException {

        }

     

        /*

         * (non-Jsdoc)

         * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest,

         * javax.servlet.ServletResponse, javax.servlet.FilterChain)

         */

        public void doFilter(ServletRequest request, ServletResponse response,

                FilterChain filterChain) throws IOException, ServletException {

     

            if ((request instanceof HttpServletRequest)

                    && (response instanceof HttpServletResponse)) {

                HttpServletRequest httpServletRequest = (HttpServletRequest) request;

                HttpServletResponse httpServletResponse = (HttpServletResponse) response;

     

                // is session expire control required for this request?

                if (isSessionControlRequiredForThisResource(httpServletRequest)) {

     

                    // is session invalid?

                    if (isSessionInvalid(httpServletRequest)) {

                        String timeoutUrl = httpServletRequest.getContextPath()

                                + "/" + getTimeoutPage();

                        logger.info("session is invalid! redirecting to timeoutpage : "

                                + timeoutUrl);

     

                        logger.info("Control on page : "

                                + httpServletRequest.getRequestURI());

     

                        String facesRequest = httpServletRequest

                                .getHeader("Faces-Request");

                        if (facesRequest != null

                                && facesRequest.equals("partial/ajax")) {

     

                            String url = MessageFormat.format(

     

                            "{0}://{1}:{2,number,####0}{3}/sessionexpired/",

     

                            request.getScheme(), request.getServerName(),

     

                            request.getServerPort(),

                                    httpServletRequest.getContextPath());

     

                            PrintWriter pw = response.getWriter();

     

                            pw.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");

     

                            pw.println("<partial-response><redirect url=\"" + url

     

                            + "\"></redirect></partial-response>");

     

                            pw.flush();

     

                        } else {

                            httpServletResponse.sendRedirect(timeoutUrl);

                        }

     

                        return;

                    }

                }

            }

            filterChain.doFilter(request, response);

        }

     

        /**

             * session shouldn't be checked for some pages. For example: for timeout

         * page.. Since we're redirecting to timeout page from this filter, if we

         * don't disable session control for it, filter will again redirect to it

         * and this will be result with an infinite loop...

         *

         * @param httpServletRequest the http servlet request

         * @return true, if is session control required for this resource

         */

        private boolean isSessionControlRequiredForThisResource(

                HttpServletRequest httpServletRequest) {

            String requestPath = httpServletRequest.getRequestURI();

     

             boolean controlRequiredLogin = !StringUtils.contains(requestPath,

                    "login");

     

                   return !controlRequiredLogin ? false : true;

     

        }

     

        /**

         * Checks if is session invalid.

         *

         * @param httpServletRequest the http servlet request

         * @return true, if is session invalid

         */

        private boolean isSessionInvalid(HttpServletRequest httpServletRequest) {

            boolean sessionInValid = (httpServletRequest.getRequestedSessionId() != null)

                    && !httpServletRequest.isRequestedSessionIdValid();

            return sessionInValid;

        }

     

        /*

         * (non-Jsdoc)

         * @see javax.servlet.Filter#destroy()

         */

        public void destroy() {

        }

     

        /**

         * Gets the timeout page.

         *

         * @return the timeout page

         */

        public String getTimeoutPage() {

            return timeoutPage;

        }

     

        /**

         * Sets the timeout page.

         *

         * @param timeoutPage the new timeout page

         */

        public void setTimeoutPage(String timeoutPage) {

            this.timeoutPage = timeoutPage;

        }

     

     

     

    And add the filter to the web.xml:

     

    <filter>

    <filter-name>SessionTimeoutFilter</filter-name>

    <filter-class>com.utils.SessionTimeoutFilter</filter-class>

    </filter>

     

    <filter-mapping>

    <filter-name>SessionTimeoutFilter</filter-name>

    <url-pattern>/*</url-pattern>

    </filter-mapping>

     

    And that's it, it is working perfectly.

  • 7. Re: RF4: Session timeout, how?
    hantsy bai Master

    This solution can not reuse  the configuration of Spring Security paths....

     

    in my project, some paths are public, some are private and protected which can be accessed by anthenticated user.

  • 8. Re: RF4: Session timeout, how?
    Fernando Castro Newbie

    I am using the above implementation, however, it does not validate the session in the call: isSessionInvalid.

    Ing a session is always valid, even when it expires.

     

    Thanks.

  • 9. Re: RF4: Session timeout, how?
    ravi j Newbie

    The above servlet solution was working well in firefox. on session time out it was redirected to the proper URL. But It is not  working in IE 8.  We are using Richfaces 4 and the ajax repsonse is malformed.

     

    Following is the response in IE 8.

     

    Server returned responseText: <?xml version="1.0" encoding="UTF-8"?> <partial-response><redirect url="http://localhost:8080/test/login.jsp"></redirect></partial-response>

    error[10:22:58.533]: Received 'error@malformedXML' event from <select id=alertTypeInfo:alertType ...>

    error[10:22:58.595]: [200] undefined: undefined

     

    Plz let me know if you have any solution for this issue.

     

     

    Thanks & Regards

    Ravi

  • 10. Re: RF4: Session timeout, how?
    ravi j Newbie

    HI,

     

    Since We are using Spring security ,I have followed the below approach  and it fixed the problem.

     

    http://stackoverflow.com/questions/10143539/jsf-2-spring-security-3-x-and-richfaces-4-redirect-to-login-page-on-session-tim

     

     

    But the issue now is with  SSO time out.

     

    Assume SSO session is timed out, application session is still active, Now if the user is performed any ajax request then SSO will interfere and tries to redirect to SSO login page. Ajax is unable to parse sso repsone and it becomes unresponsive on the page.

     

    Following exception is observed on a4j:log.

     

    error[09:41:58.012]: Received 'error@malformedXML' event from
    <div id=dashboardForm:j_id168847210_1_7848f560:1 class=rf-tr-nd rf-tr-nd-colps ...>
    error[09:41:58.013]: [200] undefined: undefined

     

     

    Any solutions/leads will be appreciated.

     

    Thanks Ravi