TurboManage

David Chandler's Journal of Java Web Development

  • David M. Chandler

    15-yr veteran of Web apps residing in Atlanta with the wife of my youth and our five children. My current project is ROA, a prayer list keeper written in GWT for AppEngine. In my "spare" time, I take pictures, preferably of Rocky Mountain National Park like the one above in which I am waving from The Keyhole.

  • Follow

  • Email Subscription

    Enter your email address to subscribe to this blog and receive notifications of new posts by email.

  • Sleepless Nights…

    August 2006
    S M T W T F S
    « May   Sep »
     12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
  • Blog Stats

    • 42,686 hits

Disable Browser Caching in JSF

Posted by David Chandler on August 8, 2006

Browser caching of page content has negative security implications when your application runs on shared terminals (like the public library). You can turn it off with this simple phase listener. Well, maybe. As some of the comments indicate, browsers are finicky, and of course, we never trust the browser, anyway, so using this technique is certainly not a security guarantee of any kind.

package my.util;

import javax.faces.context.FacesContext;
import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;
import javax.servlet.http.HttpServletResponse;

public class CacheControlPhaseListener implements PhaseListener
{
	public PhaseId getPhaseId()
	{
		return PhaseId.RENDER_RESPONSE;
	}

	public void afterPhase(PhaseEvent event)
	{
	}

	public void beforePhase(PhaseEvent event)
	{
		FacesContext facesContext = event.getFacesContext();
		HttpServletResponse response = (HttpServletResponse) facesContext
				.getExternalContext().getResponse();
		response.addHeader("Pragma", "no-cache");
		response.addHeader("Cache-Control", "no-cache");
		// Stronger according to blog comment below that references HTTP spec
		response.addHeader("Cache-Control", "no-store");
		response.addHeader("Cache-Control", "must-revalidate");
		// some date in the past
		response.addHeader("Expires", "Mon, 8 Aug 2006 10:00:00 GMT");
	}
}

To register the phase listener, just add this to your faces-config.xml:

	<lifecycle>
		<phase-listener id="nocache">my.util.CacheControlPhaseListener</phase-listener>
	</lifecycle>

25 Responses to “Disable Browser Caching in JSF”

  1. Ward said

    Thanks for the code man, I am having some issues with the back button /JSF and this is exactly the code I need. Much appreciated…

  2. Sushma said

    Thanks a lot…. It works like a charm…

  3. Lowster said

    Worked a treat, thanks.

  4. hermes said

    I am having some issues with Firefox.

  5. Sam said

    do you have a jsf example to trigger this CacheControlPhaseListener ? thanks.

  6. Sam,

    I’ve now packaged it in a jar and included a link to the download in this post. Just drop the jar under WEB-INF/lib for your application. There’s nothing else you have to do to enable it. If you use a proxy tool like Paros, you’ll be able to see the no-cache headers getting written for each request.

    /dmc

  7. Sam said

    Hi:
    I am using myfaces tobago. would there be any configuration need to do? where is the links to get the jar file? thanks again

  8. Sam said

    do I need to add the below config into my existing faces-config.xml? I tried your suggestion above and did not work. thanks agian

    com.learnjsf.util.nocache.CacheControlPhaseListener

  9. JR said

    Interesting that this gets called but does not write into the response. I threw a logger in there to make sure that its getting called but the headers don’t show up in the response.

    Any thoughts on this?
    Thanks

  10. SwappeR said

    What about Firefox 1.5? The code doesn’t work for it, it works only for IE6. Is there any solution for Firefox?

  11. THERE IS A FLAW WITH THIS TECHNIQUE.

    Here is a quote from the HTTP 1.1 specification describing the “no-cache” header:

    no-cache
    If the no-cache directive does not specify a field-name, then a
    cache MUST NOT use the response to satisfy a subsequent request
    without successful revalidation with the origin server. This
    allows an origin server to prevent caching even by caches that
    have been configured to return stale responses to client requests.

    If the no-cache directive does specify one or more field-names,
    then a cache MAY use the response to satisfy a subsequent request,
    subject to any other restrictions on caching. However, the
    specified field-name(s) MUST NOT be sent in the response to a
    subsequent request without successful revalidation with the origin
    server. This allows an origin server to prevent the re-use of
    certain header fields in a response, while still allowing caching
    of the rest of the response.

    Note: Most HTTP/1.0 caches will not recognize or obey this
    directive.

    When this response header is used without any field-name, then the cache is still allowed to store the response. It just can not re-use that response “without successful revalidation with the origin server.” Therefore, the stated aim of preventing “negative security implications when your application runs on shared terminals (like the public library)” is not achieved, since sensitive data may still be store on the shared terminal.

    Consider the use of the “no-store” header, which is more secure, but still not a guarantee of security. Here is a quote from the HTTP 1.1 specification describing the “no-store” header:

    no-store
    The purpose of the no-store directive is to prevent the
    inadvertent release or retention of sensitive information (for
    example, on backup tapes). The no-store directive applies to the
    entire message, and MAY be sent either in a response or in a
    request. If sent in a request, a cache MUST NOT store any part of
    either this request or any response to it. If sent in a response,
    a cache MUST NOT store any part of either this response or the
    request that elicited it. This directive applies to both non-
    shared and shared caches. “MUST NOT store” in this context means
    that the cache MUST NOT intentionally store the information in
    non-volatile storage, and MUST make a best-effort attempt to
    remove the information from volatile storage as promptly as
    possible after forwarding it.

    Even when this directive is associated with a response, users
    might explicitly store such a response outside of the caching
    system (e.g., with a “Save As” dialog). History buffers MAY store
    such responses as part of their normal operation.

    The purpose of this directive is to meet the stated requirements
    of certain users and service authors who are concerned about
    accidental releases of information via unanticipated accesses to
    cache data structures. While the use of this directive might
    improve privacy in some cases, we caution that it is NOT in any
    way a reliable or sufficient mechanism for ensuring privacy. In
    particular, malicious or compromised caches might not recognize or
    obey this directive, and communications networks might be
    vulnerable to eavesdropping.

  12. InterJSF said

    I am getting the following error when I dropped the jar in my web-inf/lib directory -

    [STDOUT] ERROR PhaseListenerManager – Exception in PhaseListener RENDER_RESPONSE(6) beforePhase.
    java.lang.ClassCastException: org.jboss.portlet.JBossRenderResponse
    at com.learnjsf.util.nocache.CacheControlPhaseListener.beforePhase(CacheControlPhaseListener.java:16)

  13. What about scalability? Is it really wise to disable all HTTP caching? Any reasonable web framework should let you configure domain-aware HTTP caching to reduce unnecessary load on the app and datastore.

  14. sue said

    I use this code, half work, and half does not work.

    My application: on the left side use tree for the menu, when I click the back button, the page is rollback, but the menu is not.
    any idea?

    Thanks,

  15. Murtaza said

    I was trying exactly the same concept using Servlet Filter and it was not working. Thank you.

  16. Akram Badr said

    I try to use this but i think it does not work correctly
    for example if I have web site contain a login page and after login page main page contain menu on left hand site if I clicked on menu link 1 ==> you will navigate to page 1 then click menu link 2 ==> you will navigate to page 2 then use back you will get page 1 not ==> page has expired (which is not correct), if you use back again you will get page has expired

    Any help please

    • You might try adding some logging statements to verify that the phase listener is being invoked on the transition from page 1 to page 2. Or use a Firefox plugin like TamperData to verify that the no-cache headers are being set correctly. Also try other browsers.

      • Pradip said

        Hey i’m facing the same problem.
        i have scenario like
        user goes to Search page , from there go to detail page , edit it, save it.
        now if i do back…it works fine in Firefox which takes me to edit page.
        but in IE it displays “page has expired”..

  17. Jigar said

    adding this jar into my project didnt work ..
    it is same as when jar was not present..
    when user clicks on sign out button he/she will be navigated to logoutpage where session will be destroyed..
    and then he/she will be forwarded to home page ..
    but as user clicks back button he gets all the pages..which he must not..
    browser :firefox 3.0

  18. Jigar said

    it isnt working …
    by just putting it into current project.

  19. [...] no-caching on your web application using the phaselistener (jsf [...]

  20. I updated this post to incorporate some of the comments and remove a dead link.

  21. kamaraju said

    will it work for firefox

  22. kamaraju said

    i have tried in it its not working with fire fox how to resolve it ..

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <pre> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>