26

Hello I am developing a solution in MVC in first time so I am facing a big issue, When I logout from my application(mvc razor web application) it displays login page, but if i press browser back button it displays last screen, i don't want this, i want if i press back button it still display same login page. here is my code for logout

public ActionResult Logout()
    {
        Session.Clear();
        Session.Abandon();
        Session.RemoveAll();

        FormsAuthentication.SignOut();


        this.Response.Cache.SetExpires(DateTime.UtcNow.AddMinutes(-1));
        this.Response.Cache.SetCacheability(HttpCacheability.NoCache);
        this.Response.Cache.SetNoStore();          

        return RedirectToAction("Login");
    }
Karan Prince
  • 277
  • 1
  • 3
  • 8
  • 1
    There is no reason to call Clear AND Abandon together. Pick one or the other otherwise you could have some behavioural issues in the future such as firing off Session specific events unexpectedly. – Ahmed ilyas Oct 11 '13 at 10:35
  • you say when you press the back button on the browser and it displays the last screen, what is the last screen and where is the logout being called from? surely the last screen would be a logout page thus nothing really to see? – Ahmed ilyas Oct 11 '13 at 10:55
  • Use the System.Web.Mvc.OutputCache attribute to decorate your controller or its actions. – Observer Mar 23 '16 at 14:20

6 Answers6

66

I had this problem a while ago, disabling the cache for the entire application solved my problem, just add these line to the Global.asax.cs file

        protected void Application_BeginRequest()
        {
            Response.Cache.SetCacheability(HttpCacheability.NoCache);
            Response.Cache.SetExpires(DateTime.UtcNow.AddHours(-1));
            Response.Cache.SetNoStore();
        }

Hope this helps.

AthibaN
  • 2,087
  • 1
  • 15
  • 22
  • 1
    Does this mean you can't cache _anything_ in the whole application? – Henk Mollema Oct 11 '13 at 10:27
  • 1
    nope, but when you hit back, your control hit your Action instead of loading the previously visited page directly. – AthibaN Oct 11 '13 at 10:31
  • 13
    its a bad solution to disable cache of pages for the entire application meaning even more hits to your server to execute the action again. the solution here should be an isolated one, not across the whole application. – Ahmed ilyas Oct 11 '13 at 10:34
  • @Ahmed ilyas i agree with you, server gets more hits, but it works as expected, care for a better solution ? – AthibaN Oct 11 '13 at 10:51
  • Definitely not disabling it across the application for a start :) hehe. As for a better solution - im working on it. there are so many things to consider unfortunately so its a challenge to pick the best practice and right solution for the scenario (as simple as it may seem). Remember, different browsers act differently too so that's another factor. – Ahmed ilyas Oct 11 '13 at 10:53
  • solution by Murali should be ok, alternatively http://stackoverflow.com/questions/12948156/asp-net-mvc-how-to-disable-automatic-caching-option – Ahmed ilyas Oct 11 '13 at 10:57
  • 1
    disabling the back button is just a workaround and i hope you're aware that decorating all the actions or controllers with `NoCache` is almost same as mine ! – AthibaN Oct 11 '13 at 11:01
  • Solution provided by AthibaN and Murali are considrable, my priority is to restrict go back after logout. Thanks both of you. – Karan Prince Oct 12 '13 at 09:47
  • 3
    AthibaN's solution is the best. Thank you, sir. – dailyUnknown Jul 08 '16 at 20:36
11

You need to add the cache META Tag for all the last page you visited

So add this for all the pages, by making a CustomAttribute like [NoCache] and decorate

public class NoCacheAttribute : 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.SetCacheability(HttpCacheability.NoCache);
        filterContext.HttpContext.Response.Cache.SetNoStore();

        base.OnResultExecuting(filterContext);
    }
}


public class AccountController : Controller
{
    [NoCache]
    public ActionResult Logout()
    {
        return View();
    }
}

Or try it with javascript on the page like

<SCRIPT type="text/javascript">
    window.history.forward();
    function noBack() { window.history.forward(); }
</SCRIPT>

<BODY onload="noBack();"
    onpageshow="if (event.persisted) noBack();" onunload="">
Murali Murugesan
  • 22,423
  • 17
  • 73
  • 120
6

Easiest way for a MVC 5 Application is:

[OutputCache(NoStore = true, Duration = 0, VaryByParam = "None")]

Above each of the Controller Methods you don't want to Cache. Or if you are using .Core the following works:

[ResponseCache(Location = ResponseCacheLocation.None, NoStore = true)]

Have a nice day!

ravenx30
  • 406
  • 1
  • 6
  • 11
0
protected void Application_BeginRequest()
        {
            Response.Buffer = true;
            Response.ExpiresAbsolute = DateTime.Now.AddDays(-1d);
            Response.Expires = -1500;
            Response.CacheControl = "no-cache";
            Response.Cache.SetNoStore();
        }

Add [Authorize] filter on each controller
Anup Shetty
  • 571
  • 8
  • 10
0
  protected void Application_BeginRequest()
    {
        Response.Cache.SetCacheability(HttpCacheability.NoCache);
        Response.Cache.SetExpires(DateTime.UtcNow.AddHours(-1));
        Response.Cache.SetNoStore();
        string emailAddress = null;
        var cookie =Request.Cookies[FormsAuthentication.FormsCookieName];
        // Nothing to do if no cookie
        if (cookie != null)
        {
            // Decrypt the cookie
            var data = FormsAuthentication.Decrypt(cookie.Value);
            // Nothing to do if null
            if (data != null)
            {
                // Deserialize the custom data we stored in the cookie
                var o = JsonConvert.DeserializeObject<FormsAuthenticationTicketData>(data.UserData);

                // Nothing to do if null
                if (o != null)
                    emailAddress = o.EmailAddress;
            }
        }
        SetupAutoFac(emailAddress);
    }
Amit Rana
  • 57
  • 7
0

you can use onClick event of javascript to prevent browser back. for example:

<a onclick="noBack()" href="#">Logout</a>

<Script type="text/javascript">
     window.history.forward();
     function noBack() { window.history.forward(); }
</Script>

Hope this will help you, Happy Coding!