0

I am confused about how sessions are managed in JSF 2.0.

I created 4 pages with login, data, info and sessionexpires that shows once session has expired.

When I click on logout button, it invalidates session by calling the following action method:

public String logout(){
    FacesContext.getCurrentInstance().getExternalContext().invalidateSession();
    return "logout?faces-redirect=true";
}

The code redirects me to logout page, as expected, but when I click browser's back button it takes me to the data page and shows all info, but i think, if session has already expired then it should show sessionexpires page.

How can I achieve the desired functionality?

skuntsel
  • 11,624
  • 11
  • 44
  • 67
Muzzammil Ayyubi
  • 53
  • 1
  • 2
  • 11
  • possible duplicate of [Avoid back button on JSF web application](http://stackoverflow.com/questions/10305718/avoid-back-button-on-jsf-web-application) – BalusC Jul 23 '13 at 12:51
  • Thanks alot @BalusC, but still my question is not exactly cached pages on click of back button, but on cached pages why action performs on click of command button if i am invalidating the session – Muzzammil Ayyubi Jul 25 '13 at 17:29

2 Answers2

4

The fact that you see previous pages when user clicks browser's back button indicates that the pages were cached and are displayed from browser's cache rather that requested from server. To fix it you need to set HTTP response headers appropriately. This has been answered beforehand in Making sure a web page is not cached, across all browsers. Just to repeat BalusC, these are:

response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
response.setHeader("Pragma", "no-cache"); // HTTP 1.0.
response.setDateHeader("Expires", 0); // Proxies.

The most appropriate place to set these headers is a web filter, as you don't seem to need any of JSF belongings there. You can find more information in the answers to Avoid back button on JSF web application. To repeat BalusC's code, you'll have:

@WebFilter("/secured/*")
public class NoCacheFilter implements Filter {

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;

        if (!request.getRequestURI().startsWith(request.getContextPath() + ResourceHandler.RESOURCE_IDENTIFIER)) { // Skip JSF resources (CSS/JS/Images/etc)
            response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
            response.setHeader("Pragma", "no-cache"); // HTTP 1.0.
            response.setDateHeader("Expires", 0); // Proxies.
        }

        chain.doFilter(req, res);
    }

    // ...

}

Just don't forget to tell which pages you need to filter. This way the new pages requested will always be sent from server and won't be cached anymore. So, if user tries to access a secured page after logout happened (by means of session invalidation and sending a redirect), your standard security means will kick in (other filter) preventing user from gaining access to those pages.

The next thing to do is to explain JSF how to deal with the already opened pages when session was invalidated / timed out. In other words, how can you deal with ViewExpiredExceptions. This is in turn answered in How to handle session expiration and ViewExpiredException in JSF 2? and javax.faces.application.ViewExpiredException: View could not be restored for synchronous POST requests and in Session timeout and ViewExpiredException handling on JSF/PrimeFaces ajax request for AJAX requests.

Basically, for the former you need to add the following lines to your web.xml:

<error-page>
    <exception-type>javax.faces.application.ViewExpiredException</exception-type>
    <location>/expired.xhtml</location>
</error-page>

For the latter I warmly recommend you to take a look at JSF utility library OmniFaces and its FullAjaxExceptionHAndler that was designed for this purpose.

Community
  • 1
  • 1
skuntsel
  • 11,624
  • 11
  • 44
  • 67
  • thanks alot @skuntsel, but still what i am trying to do is when person clicks on that cached page command button it should take to sessionsexpires page (as i invalidated sessions), but not to perform action on click of that button – Muzzammil Ayyubi Jul 24 '13 at 07:24
0

The browser takes you back to the data page even after the session has been invalidated on the server is because the page is cached in your browser memory.

Follow this on how a browser's back button works.

You can refer this for tackling your problem.

Community
  • 1
  • 1
joe
  • 1
  • thanks @joe, but this is not my problem, i know page is cached as i learnt from [here](http://stackoverflow.com/questions/5619827/how-to-invalidate-session-in-jsf-2-0) by BalusC, but again on the back page if i click any command button it should take me to sessionexpire page, but not to requesting page by that button. – Muzzammil Ayyubi Jul 23 '13 at 06:24