Prevent user from seeing previously visited secured page after logout
Asked Answered
M

7

105

I have the requirement that the end user should not be able to go back to the restricted page after logout/sign out. But currently the end user is able to do that by the browser back button, visiting browser history or even by re-entering the URL in browser's address bar.

Basically, I want that the end user should not be able to access the restricted page in any way after sign out. How can I achieve this the best? Can I disable the back button with JavaScript?

Mycosis answered 16/11, 2010 at 12:40 Comment(1)
Use Post-request-get pattern.Google it.Changeover
D
143

You can and should not disable the browser back button or history. That's bad for user experience. There are JavaScript hacks, but they are not reliable and will also not work when the client has JS disabled.

Your concrete problem is that the requested page is been loaded from the browser cache instead of straight from the server. This is essentially harmless, but indeed confusing to the enduser, because s/he incorrectly thinks that it's really coming from the server.

You just need to instruct the browser to not cache all the restricted JSP pages (and thus not only the logout page/action itself!). This way the browser is forced to request the page from the server instead of from the cache and hence all login checks on the server will be executed. You can do this using a Filter which sets the necessary response headers in the doFilter() method:

@WebFilter
public class NoCacheFilter implements Filter {

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

        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);
    }

    // ...
}

Map this Filter on an url-pattern of interest, for example *.jsp.

@WebFilter("*.jsp")

Or if you want to put this restriction on secured pages only, then you should specify an URL pattern which covers all those secured pages. For example, when they are all in the folder /app, then you need to specify the URL pattern of /app/*.

@WebFilter("/app/*")

Even more, you can do this job in the same Filter as where you're checking the presence of the logged-in user.

Don't forget to clear browser cache before testing! ;)

See also:

Diphenylhydantoin answered 16/11, 2010 at 12:46 Comment(7)
Sometimes this is not enough, I remember having such an issue. The browser just remembers the last page. But it might have been IE6, I can't recall :)Archaism
@Bozho: Either you've provided an incomplete set of headers or the browser has the page still in its cache.Diphenylhydantoin
@Chris: works for me with Firefox and all other browsers. Your problem is caused elsewhere. Perhaps you forgot to clear some cache? Or those headers are set on the wrong responses?Diphenylhydantoin
@Diphenylhydantoin I created a separate Filter class to override the doFilter() method. When I press the logout button it is redirected to a servlet where in I invalidate the session. I'm not sure how the doFilter() method come into play here. Can you please tell me how to implement this? As in, the correct steps to follow. Thanks.Canarese
Worked well for me. Tested after both sendRedirect(...) and forward().Sternwheeler
@Diphenylhydantoin You have not used variable hsr in doFilter() is this what you intended or their is some mistake ?Variance
I use spring mvc, have tried these lines of code in many many different styles, also in the original format you've written, but it just doesn't work for me, is it because of spring mvc or something? please advice.@DiphenylhydantoinDigress
H
5

*.jsp in Url Pattern won't work if you forward a page. Try to include your servlet too.. that will make your application secure from this back button problem.

Heidt answered 3/3, 2012 at 20:28 Comment(0)
B
2

The simplest way to do it without disabling the browser back buton is by adding this code to the page_load event for the page that you don't want the user to go back to after logging out:

if (!IsPostBack)
    {
        if (Session["userId"] == null)
        {
            Response.Redirect("Login.aspx");
        }
        else
        {
        Response.ClearHeaders();
        Response.ClearContent();
        Response.Clear();
        Session.Abandon();
        Session.Remove("\\w+");
        Response.AddHeader("Cache-Control", "no-cache, no-store, max-age = 0, must-revalidate");
        Response.AddHeader("Pragma", "no-cache");
        Response.AddHeader("Expires", "0");
        }
    }
Biauriculate answered 29/6, 2015 at 15:44 Comment(1)
Though your answer is useful, please post the answer that relates to the OP's programming language of choice. Your C# solution won't help in the OP's Java EE project.Intramural
B
1

The correct way to do this is to add the

Vary: Cookie

header on secured pages. When the user logs out, clear their session cookie. Then, when they navigate back after logging out, the browser cache will miss. This also has the benefit of not completely defeating caching.

Bunin answered 5/11, 2016 at 12:38 Comment(0)
A
0

You can try telling the browser not to cache the homepage (using the appropriate headers - Expires, Cache-Control, Pragma). But it is not guaranteed to work. What you can do, is make an ajax call to the server on page load to check if the user is logged, and if not - redirect.

Archaism answered 16/11, 2010 at 12:46 Comment(1)
But if an evil mind disables JavaScript this does not work and he will see the page nevertheless.Kate
B
0

An alternative to implementing a Filter is to set a 'no-cache' filter on all the secured JSPs, or on all paths. This may be a good idea if the application is small, and if you would like to customize this property for a specific pages only. We can add the following Java snippet on every secured JSP that should not be cached:

<%
  response.addHeader("Pragma", "no-cache");
  response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
  response.setDateHeader("Expires", 0);
%>

If not on JSP, this could also be used in Controllers where routing is defined and set the headers for the 'HttpServletResponse' object.

Bourn answered 18/6, 2021 at 9:17 Comment(0)
J
0

For me the problem was , I didn't want to set headers on all pages , so I just set this header on page when logout is clicked and it clears everything related to the site :)

// Removes all site data
response.setHeader ("Clear-Site-Data", "\"cache\"");

Please read more about it over here : https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Clear-Site-Data

Jeanette answered 1/11, 2021 at 15:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.