That should never happen.
Without any code samples which I can look it, one reason I can envision that happening is an authentication workflow as shown below:
In the following diagram, /login
POSTs to /member
, where the authentication check takes place.
If authentication passes, the pages continues to send the 'logged in user' content. This makes this page (/member
) appear into browsers history. Anytime you click back/forward button on your browser to come to this page, it will ask you if you want to POST the form content on this page. In this case, the date is login credentials.
WRONG WAY:
+---------------------------+ +------------------------------+
| Login Page (/login) | | Member Page(/member) |
|---------------------------| |------------------------------|
| +--------------+ | | if creds wrong |
| UserName | | | | redirect_to /login |
| +--------------+ |+-------->| else |
| +--------------+ | | "Welcome Back, |
| Password | | | | Here is your super secret |
| +--------------+ | | member area where you can |
| | | check out the cool stuff" |
+---------------------------+ | end |
+------------------------------+
Instead you should have this kind of authentication flow:
- Login page posts to a
/verify
(or /auth
whatever you call it) page.
- The verification page does not have any http output. Based on whether the creds are good or bad it just redirects to the appropriate page. If login is good, it sets a cookie flag indicating a valid session.
- Member page validates the session by checking the cookie value and redirects to
/login
page if session is expired/not-set.
In this workflow, /verify
page never appears in the browser history and there is no way user can 'click refresh' on that page to trigger POST data getting sent again.
CORRECT WAY POST +-----------------------------+
+------------>| Verify page (/verify) |
| |-----------------------------|
+-------------------------+-+ | if creds wrong |
| Login Page (/login) |<---+---------+redirect_to /login |
|---------------------------| | | else |
| +--------------+ | | | set_session_cookie |
| UserName | | | | +-------+redirect_to /member |
| +--------------+ | | | | end |
| +--------------+ | | | | |
| Password | | | | | +-----------------------------+
| +--------------+ | | |
| | | | +------------------------------+
+---------------------------+ | +----->| Member Page(/member) |
| |------------------------------|
| | if session_cookie not set |
+-----------+redirect_to /login |
| else |
| "Welcome Back, |
| Here is your super secret |
| member area where you can |
| check out the cool stuff" |
| end |
+------------------------------+
This is the common Post/Redirect/Get model. You can check this wiki page for prettier pictures: http://en.wikipedia.org/wiki/Post/Redirect/Get
Also, if you want to prevent the browser to cache certain HTML pages, you can set the cache-control HTTP header to 'no-cache' for those pages.
Cache-Control: no-cache