This is probably overly simple, but I felt like posting something anyway…
Every once in a while you hear a complaint that you’ve got some sort of login (account), then a user actually logs out, and then yet, hits the back button in their browser… and, whoopty-doo, they get back to see the account information. Which, of course, comes from the cached browser page.
First, let’s take a decent web-app, like facebook or gmail and see what happens…
Login, logout, click “Back” and we are not going to see our cached page from the browser. Instead we get redirected back to the login page (or whatever you decide for your specific app).
So, what’s their solution?
Nothing special, really, just sending the right headers via PHP to let the browser know not to cache any account pages. (Sure there are other implications involved, so you might consider a redirect while doing the logout).
Let’s try and do it the cake-way…
Say, we have a purchase something page, and the user fills out the form and then gets a “thank you” (or confirmation) page.
If the they click “back” in the browser we do not want to re-display the purchase form. Rather we’d have some page, that would say something like “Hey, you’ve just made the purchase. Don’t be a moron and click back to have your credit card charged twice, but if you really wish to… please, click here and do another purchase”.
First, we’ll disable caching for the purchase page:
if($this->action == 'purchase') {
$this->disableCache();
}
}
Yep, $this->disableCache() will tell cake to send the right header in order to prevent the page from caching.
Surely, we’ll have a “purchase” action in our Controller (let’s say Users Controller).
if(!empty($this->data)) {
//write whatever we need to our DB and perhaps talk to the payment method processor.
//also, just in case, let's write something to the user's session
//... and do redirect to the "thank you" page
$this->Session->write('Purchased', true);
}
else {
//and now we do our check for the silly user who tried to click "back"
if($this->Session->check('Purchased')) {
$this->render('silly_user_you_have_already_made_a_purchase');
}
}
}
I hope you see how this all works, based on the rather simple code above.
To sum things up…
- We ensure that purchase form is not cached
- When the purchase is complete we keep a track of that in the session
- If the user clicks “back” in the browser we render a different view (than the purchase form) based on the value in the session