1

To make it short, here is the scenario:

  • The browser back button must be functional (I'm using JSF 2.0, so this is working)

  • After logout, if a user clicks the back button, the app must redirect him/her to the login page (not working, the user is able to view protected pages, although expired. I can´t include the meta tags to disable browser caching because the back button stops working)

  • If the user invokes an action, by clicking a button, on one of the expired pages it should redirect him/her to the login or error page (not working, the app throws an error and shows a blank page. My ExceptionHandlerWrapper implementation detects the exception and it is using a NavigationHandler to change the viewId and render the response ("facesException" mapping on faces-config that points to login.jsf), but the app is not behaving as expected)

Can someone please help me to solve this problem?

Fahim Parkar
  • 30,974
  • 45
  • 160
  • 276
Carlos Ferreira
  • 565
  • 1
  • 8
  • 15

1 Answers1

1
  • The browser back button must be functional (I'm using JSF 2.0, so this is working)

  • After logout, if a user clicks the back button, the app must redirect him/her to the login page (not working, the user is able to view protected pages, although expired. I can´t include the meta tags to disable browser caching because the back button stops working)

Two steps to solve this problem.

  1. Disable browser cache by setting response headers accordingly. You can do this in a Filter which is mapped on the FacesServlet.

    HttpServletResponse hsr = (HttpServletResponse) response;
    hsr.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
    hsr.setHeader("Pragma", "no-cache"); // HTTP 1.0.
    hsr.setDateHeader("Expires", 0); // Proxies.
    chain.doFilter(request, response);
    
  2. Do not use HTTP POST for page-to-page navigation. Always use HTTP GET for page-to-page navigation. If you need to submit a form, let it submit to self (i.e. let action method return null or void) and use h:messages or h:somecomponent rendered="#{success}" to display results in the same page conditionally.


  • If the user invokes an action, by clicking a button, on one of the expired pages it should redirect him/her to the login or error page (not working, the app throws an error and shows a blank page. My ExceptionHandlerWrapper implementation detects the exception and it is using a NavigationHandler to change the viewId and render the response ("facesException" mapping on faces-config that points to login.jsf), but the app is not behaving as expected)

An <error-page> on javax.faces.webapp.ViewExpiredException was been enough. See also this answer.

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • Hi, Thanks for your reply. Unfortunately, your solution can't be used, because the app is already built. The majority of the forms submit to a confirmation page and it would mean that the all app would have to be changed. – Carlos Ferreira Mar 03 '11 at 12:36
  • And what about the back button? Wouldn't your solution mess with it? – Carlos Ferreira Mar 03 '11 at 12:41
  • No because there's then only GET for page-to-page navigation. It are only the POST requests with no-cache headers which give this kind of expired warning when navigating back. You could also introduce the PRG pattern, Post-Redirect-GET, add `` to navigation case. But this involves other desastreus changes (request scoped beans will be garbaged too soon). – BalusC Mar 03 '11 at 12:45
  • Regarding the ViewExpiredException, I tried via web.xml and via ExceptionHandlerWrapper, but both fail to show the login page (in fact, it says that the expired page is login.jsf). – Carlos Ferreira Mar 03 '11 at 12:57
  • Is it an ajax or normal request? If ajax, you need to send a redirect instead of replacing `viewId`. – BalusC Mar 03 '11 at 13:03