Solved

Problem: After a visitor logs out, his "Back" button still gets him to the protected pages

Posted on 2007-12-03
26
337 Views
Last Modified: 2013-12-25
Hi,
I'm having a browser cache problem that I can't seem to control.  I'm working on a site that a user must log into; a successful login leaves an authentication cookie on his computer.  When he clicks "log-out", the code in the cookie is invalidated, and he is taken to a non-protected page, like a FAQ page, or the "log in again" page.  When that happens, if he clicks the "Back" button on the browser, he's back at the protected page, even though his cookie has now been invalidated.

I thought I was controlling against that.  The protected page prints like this:

print "Content-type: text/html\n\n";
print "Cache-Control: no-cache\n";
print "Expires: Sun, 28 Jul 2002 08:12:13 GMT\n";  # just some time in the past

Then comes the <DOCTYPE> declaration, and then the html.

What am I doing wrong?  Am I on the right track?
I've read a bunch of tutorials on this topic on the Web, and it *seems* like I'm doing things right, but I must be missing something.

Thanks,
--Steve


0
Comment
Question by:StevenMiles
  • 8
  • 7
  • 7
  • +3
26 Comments
 
LVL 2

Expert Comment

by:tryokane
Comment Utility
i dunno much about this. But suppose some pages you have seen, they say that you have changes have been made to the page you have submited and you have to refresh the page, i think a lot of pages use such a control to stop people from using that back button to go back to the protected page?
0
 
LVL 17

Expert Comment

by:mjcoyne
Comment Utility
Try Including these headers:

<META HTTP-EQUIV="CACHE-CONTROL" CONTENT="NO-CACHE">
<META HTTP-EQUIV="PRAGMA" CONTENT="NO-CACHE">
<META HTTP-EQUIV="Expires" CONTENT="-1">

0
 
LVL 48

Assisted Solution

by:Tintin
Tintin earned 30 total points
Comment Utility
You have the order of the headers incorrect.  

You really should be using the standard CGI module to ensure your headers are generated correctly, eg:

use CGI ':standard';
print header(-expires=>'-1d');

0
 
LVL 7

Assisted Solution

by:rugdog
rugdog earned 20 total points
Comment Utility
you are indicating the headers are done after the second \n of your first print, so I'd re-write it like this:

print "Content-type: text/html\n";
print "Cache-Control: no-cache\n";
print "Expires: Sun, 28 Jul 2002 08:12:13 GMT\n\n";  # just some time in the past
0
 

Author Comment

by:StevenMiles
Comment Utility
Hi, everybody,
Thank you for your input.  Here's what happened:
mjcoyne's suggestion didn't work.  No offense, but I read in several places that that solution isn't very effective: it has to be done at the header level.
rugdog's solution didn't work, and I tried Tintin's solution of using the CGI module, too, and even that didn't work.  I could tell that the page was still cacheing, because the perl program that prints out the html is peppered with "print STDERR" statements, so that I can see what's going on, and I was watching the "tail -f" of the error file, and it was clear when I hit the back button that the perl program didn't run, but rather the browser just snapped the supposedly-protected page back into view.

There's got to be a way to do this.  When I'm logged in to my bank's Web site, every time I hit the "back" button, it gives me the "Webpage has expires" message.  Is there a way I can see the headers that the bank is sending to my browser, or any other ideas?

Thanks again,
Steve
0
 
LVL 48

Expert Comment

by:Tintin
Comment Utility
What browser are you using?  I'm going to guess FIrefox.
0
 
LVL 51

Expert Comment

by:ahoffmann
Comment Utility
>What am I doing wrong?
nothing
>Am I on the right track?
yes

The pages are cached by the browser, hence when you use the "back" button the browser simply displays what's already there. Any cache headers or pragmas, either in the HTTP header or HTML body can prevent this.

You can do following to force the Browser to reload the page:
 use a POST request for those pages which should not be accessable with the back button
 this POST request contains a random value as parameter
 the response to the request is a 30x status with a Location: header pointing to the right content
This is no bullet prove solution but will most likely prevent going back simply.
0
 

Author Comment

by:StevenMiles
Comment Utility
Hi again,
All of the pages that contain protected content are generated as the result of a POST.  In fact, if I ask for a "refresh" of the page, I get the little dialog box that says the browser needs to resend the information.  If I log out, then use the back button to get to the protected page, then click "refresh", when it resends the POST info, I get dumped back to the "need to login again" page, which is what I'd like to have happen when the back button is pressed.  This behavior is the same in IE and Firefox.
ahoffman, I guess I didn't understand your response completely.  Can you spell it out for me in more detail, so I can be sure I understand it?
Thanks,
Steve
0
 
LVL 17

Expert Comment

by:mjcoyne
Comment Utility
"but I read in several places that that solution isn't very effective: it has to be done at the header level."

From W3.org (see http://www.w3.org/TR/html401/struct/global.html#h-7.4.4):

"The http-equiv attribute can be used in place of the name attribute and has a special significance when documents are retrieved via the Hypertext Transfer Protocol (HTTP). HTTP servers may use the property name specified by the http-equiv attribute to create an [RFC822]-style header in the HTTP response. Please see the HTTP specification ([RFC2616]) for details on valid HTTP headers.

The following sample META declaration:

<META http-equiv="Expires" content="Tue, 20 Aug 1996 14:25:27 GMT">

will result in the HTTP header:

Expires: Tue, 20 Aug 1996 14:25:27 GMT"


So, meta tags *are* headers, and adding them to your page *is* working "at the header level".  That's why they're placed between the <head> tags...
0
 

Author Comment

by:StevenMiles
Comment Utility
Hi, mjcoyne,
Okay.  I stand corrected, and I apologize.  I went ahead and put the statements in the <head> section, but it didn't work.  'Seems that no matter what I do, when I hit the back button, the browser just instantaneously shows me the previous page, without checking with the server first.  I'm still interested in more on ahoffman's idea ...
0
 
LVL 17

Expert Comment

by:mjcoyne
Comment Utility
Understood.  Chaches are tricky.  As you're doing each of your tests, you should clear your browser chache first to make sure you're not seeing a prior copyof the page already cached, and/or change something on your page text to be sure you're looking at the right page.
0
 

Author Comment

by:StevenMiles
Comment Utility
Hi again,
Okay, more info.  I logged in, viewed a couple of protected pages, logged out, then cleared the browser cache, then hit the back button, and as expected, it said the page had expired and there was nothing to see.  Then I logged in again, viewed some pages, logged out, hit the back button, and there was the protected data again.  Arrrrrgh.
I found this at http://support.microsoft.com/kb/199805 :
"For these dynamic files, Web servers should include the HTTP 1.1 "Cache-Control: no-cache" header in the HTTP response as described in the HTTP 1.1 recommendation to prevent the file from caching.  Note that it is essential to use HTTP Headers instead of META HTTP-EQUIV tags. META tags are not evaluated until after downloaded files have already been stored in the cache."
This is so frustrating because I *know* there are lots of people out there who have already solved this problem in their applications!  I live in Omaha.  Maybe I should walk over to PayPal and ask to talk to the chief programmer.
--Steve
0
 
LVL 51

Expert Comment

by:ahoffmann
Comment Utility
> Can you spell it out for me in more detail,
where do you have problems in my description?
0
Threat Intelligence Starter Resources

Integrating threat intelligence can be challenging, and not all companies are ready. These resources can help you build awareness and prepare for defense.

 
LVL 17

Expert Comment

by:mjcoyne
Comment Utility
Note that on the page you've linked to, MS explicitly distigushes cache behavior from history (back button) behavior.  I think this is part of the problem you're having: "why shouldn't an authorized (logged-in) person be able to see the page in his history?  He was authorized to see it at the time, why can't he see it again?" is the logic of the history behavior.  Of course, there are many reasons that one might not want the back-button to work this way...

With regard to the caching quirks, the problem is that MS makes up its own rules -- I'll bet if you try your http-equiv headers with Firefox or Opera, they'll work as advertised...

Anyway, there is a work-around available for IE that's all over the internet.  The solution is (apparently; I haven't tried it myself) to include the http-equiv meta tags in the head section as usual, but then to also repeat them in a second head section outside the body of the page but before the </html> closing tag.  So, your page is constructed this way:

<html>
<head>
<meta http-equiv="PRAGMA" content="NO-CACHE">
</head>
<body>

Your page's content goes here

</body>
<head>
<meta http-equiv="PRAGMA" content="NO-CACHE">
</head>
</html>

Note also that IE 5 needs even more:  it's the same "two head sections" workaround, but in each of these sections you must also include the <meta http-equiv="EXPIRES" content="-1"> statement in addition to the no-cache pragma line.

You can also try printing the statements directly; something like:

print "Content-type: text/html\n";
print "Pragma: no-cache\n";
print "Cache-control: no-cache\n";
print "Expires: -1\n";
print "\n";

Personally, I'd do both -- include the double <head> sections with meta tags, and print the statements directly along with the mime type.


0
 
LVL 51

Expert Comment

by:ahoffmann
Comment Utility
please keep in mind that the cache problem is different to the natural behaviour of the browser's back button (kkeping bugs and quirck beside)

I don't see a reason why goning back in history should not display what already have been seen. Things change if going back requests the page again (which is the point where the cache controls the game), then your application have to make precautions and return proper content.
0
 
LVL 17

Expert Comment

by:mjcoyne
Comment Utility
If that doesn't work, try replacing the short cut Expires: -1 syntax with a full valid date in the past:

print "Expires: Monday, 25-Dec-06 05:29:10 GMT\n\n";
0
 
LVL 17

Expert Comment

by:mjcoyne
Comment Utility
I agree, ahoffmann -- that's why I also pointed it out to StevenMiles in my reply.  However, there are several instances in which one might not want the back button to behave that way -- for example, a page from which someone hits a "Purchase" button, and then is acknowledged with a "Thank You" page.  You wouldn't necessarily want people being able to go back to the "submit purchase" page without re-initiating the purchase...

There are, however, differences in how these two things behave.  So, while we might be able to control the cache from the server side, there's no guarantee that this will also control any given browser's back button  -- "cache" and "history" are not interchangable terms.

StevenMiles -- note that the page you linked to is talking about Microsoft Internet Explorer 5.0 (we're up to version 7 now) and links to a draft of the HTTP 1.1 specifications -- "Expires March 11, 1999".  The finalized version is RFC2616, see http://www.faqs.org/rfcs/rfc2616.html.
0
 
LVL 51

Expert Comment

by:ahoffmann
Comment Utility
> .. "cache" and "history" are not interchangable terms.
that's what I said (probably not that clear:)
hence we have to provide a solution completely done by the application, not relying on browser quircks or caches inbetween somewhere, see my suggestion http:#20405630
0
 

Author Comment

by:StevenMiles
Comment Utility
Thank you for continuing to help.  I put the no-cache and expires statements in both <head> sections, and used the full expire statement there and in the pre-html headers that the perl program writes out.  Still doesn't work in IE.

Sorry about not noticing that the MS document was for IE 5.  I really *am* trying to do my homework here.  

It's true that in Firefox, when I log out and then hit the back button, the browser gives me a button to repost my data, and when it's reposted, of course, I don't see the protected pages, because I'm logged out.  Nice.  Opera, however, gives the same behavior as IE.

Here's why I'd like to have this work: an average user accesses his account on a computer that co-workers have access to, or perhaps he's at an Internet cafe.  He does his stuff, clicks the LogOut button, and walks away.  The next person to the computer hits the back button, and see's his account information!

If you log into your PayPal account, then hit the LogOut link, then hit the back button, you are taken to a page that tells you that you must log in before viewing this page.  There isn't even a request from the browser to re-post the data!  That's exactly the type of behavior I'd like to emulate.
/SD
0
 
LVL 51

Expert Comment

by:ahoffmann
Comment Utility
if you really want to beat all the browser dragons, try following

print
 header("Expires: 0"),
 header("Pragma: no-cache"),
 header("Cache-Control: no-cache, no-store, must-revalidate"),
 header("Cache-Control: post-check=0, pre-check=0", false),
 '<META HTTP-EQUIV="Last-Modified  CONTENT="Mon, 26 Jul 1997 05:00:00 GMT">
<META HTTP-EQUIV="Expires"       CONTENT="Fri, Jun 12 1981 08:20:00 GMT">
<META HTTP-EQUIV="Pragma"        CONTENT="no-cache">
<META HTTP-EQUIV="Cache-Control" CONTENT="no-cache, no-cache, must-revalidate">
<META HTTP-EQUIV="Cache-Control" CONTENT="post-check=0, pre-check=0, false">';
0
 
LVL 17

Expert Comment

by:mjcoyne
Comment Utility
You can also try a little javascript:

<head>
<script language="javascript">
<!--
location.replace("pagename.html")
//-->
</script>
...other head section stuff...
</head>

where "pagename.html" is the name of the page you want them to see when the back button is clicked.
0
 
LVL 51

Expert Comment

by:ahoffmann
Comment Utility
how should JavaScript help to inhibit viewing pages from the history (if I simply can disable such malware:)
0
 
LVL 17

Accepted Solution

by:
mjcoyne earned 100 total points
Comment Utility
"Syntax: location.replace(URL)
The replace method replaces the current History entry with the specified URL. After calling the replace method, you cannot navigate back to the previous URL using the browser's Back button."

Sure, it won't work if you have Javascript disabled, but most casual users do not have JS disabled, and it brings StevenMiles one step closer to his goal, since I'm certian we're not dealing with a cache issue anymore but instead one of the behavior of the back button.
0
 

Author Comment

by:StevenMiles
Comment Utility
I used IEWatch Professional (from iewatch.com -- it lets you see various information, such as headers being sent to your browser) to look at PayPal's headers when I log out from them.  Here's what they send:
Cache-control: no-cache, no-store, must-revalidate, max-age=0, proxy-revalidate, no-transform, private

I also found another way to disable the back button:
<body onload="history.forward(1)">
Seems to work.  I don't like changing how the back button works, because the user loses his intuitive idea of the way a site works, but if I can't get this no-cache thing figured out, maybe I could disable the back button *only* for the exact page that a user is sent to when he explicitly clicks a link to log himself out.

I'd welcome any comments, or any other possible ways to try to emulate the PayPal restriction on jumping back to the data after logging out.
/S
0
 
LVL 51

Assisted Solution

by:ahoffmann
ahoffmann earned 100 total points
Comment Utility
history.forward(1) does not work if malware is disabled, obviously ...
0
 

Author Closing Comment

by:StevenMiles
Comment Utility
Since we discussed this, I found that I can be working on *my bank's** site, log out, press the "back" button, and get back to my account!
0

Featured Post

Better Security Awareness With Threat Intelligence

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
Perl Frameworks 1 51
Joomla Website Malfunction 9 48
Web Browsers Start Page Hijacker 14 71
Perl script to delete older files 6 42
Internet is a big network which is formed by connecting multiple small networks.It is a platform for all the users which are connected to it.Internet act as platform in different fields. Such as: Internet  as a collaboration platform. Internet  as…
Introduction If you're like most people, you have occasionally made a typographical error when you're entering information into an online form.  And to your consternation, the browser remembers the error, and offers to autocomplete your future entr…
Learn the basics of modules and packages in Python. Every Python file is a module, ending in the suffix: .py: Modules are a collection of functions and variables.: Packages are a collection of modules.: Module functions and variables are accessed us…
The viewer will learn the basics of jQuery, including how to invoke it on a web page. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery.: (CODE)

763 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now