Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web

Web Development - Disabling the Back Button

4.67/5 (5 votes)
15 Mar 2012CPOL4 min read 16.2K  
Web development - disabling the back button

Time and again, this question seems to come up on forums.

"I have a page that can only be seen by logged in users, but when they logout then click the back button, they see the page that should only be for logged in users. How do I disable the back button?"

This is because of caching on the browser and the way browser history works. The short answer to this question is:

You don't disable the back button. The back button isn't yours to disable, it's part of my browser and I want it to work.

Usually, when people post questions like this, it's because they don't understand how to control the flow of data from the site. In this case, the two things we are concerned with are authentication and caching.

As a web developer, you have full control of your server code but only limited control of the client in terms of scripting. You cannot even guarantee that the client will have any scripting capabilities (a user may disable script until they trust your site, I certainly do!), so you should never design your site behaviour from the client's perspective - i.e., trying to disable the back button of a browser.

Instead, if you need to implement behaviour so that when a logged out user clicks the back button, they are redirected to a login page, you need to design your site so that this will occur. Your server side design should drive the client behaviour,

You need to consider the following points:

  1. Secure all of the resources that require authentication

    For ASP.NET authentication to work, you must indicate which items in your site should require the user to be logged in. From an ASP MVC point of view, this would mean that actions should have the Authorize Attribute applied to them.

    For a standard ASP.NET site, you would achieve this using Authentication and Authorization settings in your web.config file, locking down parts of your site.

  2. Indicate which items should never be cached on the client

    By using caching directives, when your resources are requested, you can include instructions that tell the browser "don't cache this content, always ask for it again". In .NET, this is achieved by using the Response Stream and the Cache settings. e.g.

    C#
    Response.Cache.SetCacheability(System.Web.HttpCacheability.NoCache);
    Response.Cache.SetNoStore();

    In MVC, you could create an action filter that performs this behaviour. (These examples were taken from a thread on StackOverflow.)

    C#
    public class NoCache : ActionFilterAttribute
    {  
        public override void OnResultExecuting(ResultExecutingContext filterContext)
        {
            filterContext.HttpContext.Response.Cache.SetExpires(DateTime.UtcNow.AddDays(-1));
            filterContext.HttpContext.Response.Cache.SetValidUntilExpires(false);
            filterContext.HttpContext.Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
            filterContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
            filterContext.HttpContext.Response.Cache.SetNoStore();
    
            base.OnResultExecuting(filterContext);
        }
    }

    You can then apply this attribute on your controllers or actions as required, e.g.

    C#
    [NoCache]
    [HandleError]
    public class AccountController : Controller
    {
        [NoCache]
        [Authorize]
        public ActionResult ChangePassword()
        {
            return View();
        }
    }

    You could also simply use the OutputCache attribute to specify no caching on the client.

    C#
    [HttpGet]
    [OutputCache(NoStore = true, Duration = 60, VaryByParam = "*")]
    public ViewResult Index()
    {
      ...
    }

    In a standard ASP.NET page, you could just add settings to the Page Load to specify the directives, e.g.:

    C#
    HttpContext.Current.Response.Cache.SetExpires(DateTime.UtcNow.AddDays(-1));
    HttpContext.Current.Response.Cache.SetValidUntilExpires(false);
    HttpContext.Current.Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
    HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
    HttpContext.Current.Response.Cache.SetNoStore();

What Does This Achieve?

Once you have this in place, when your user clicks the back button, they will not see cached content from your browser - we have disabled that. Therefore, they are forced to go back to the URL that content was served from. When the request is received, authentication will determine that the user is no longer logged in and cannot access the resource, and they should be automatically redirected to your login page.

The combination of authentication and caching settings on the server will dictate how the browser will behave. We no longer need to disable the back button, the user cannot access the cached resource any more.

Other Considerations

Another good point made in this thread that I shall summarize here. You should ask yourself, does it really matter if the user sees the cached content?

They can view the details in their cache, but if they try to interact with anything (e.g. make a POST by submitting the form), then authentication will take place again and the user is forced to login. So, is it really a problem if they can view their cached content?

In a few high security situations, then yes it matters (e.g. pages that display payment details, bank details - anything involving money or confidential information) and you should use the caching directives. Otherwise, don't completely disable client side caching just because you can. If you do this, then even when the user is logged in the back \ forward buttons of the browser will always request content from the server and you have stopped the ability of the user to browse their client side cache.

Hopefully, you now have enough information to make a decision and implement caching.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)