Using hash to check if page with $_POST values was refreshed
When posting a form to the same PHP page, what is the correct method to find if the page was accidentally refreshed instead of submitted again?
Here's what I'm using right now:
$tmp = implode('',$_POST);
$myHash = md5($tmp);
if(isset($_SESSION["myHash"]) && $_SESSION["myHash"] == $myHash)
{
header("Location: index.php"); // page ref开发者_如何学编程reshed, send user somewhere else
die();
}
else
{
$_SESSION["myHash"] = $myHash;
}
// continue processing...
Is there anything wrong with this solution?
UPDATE: An example for this scenario would be inserting a row into a registration table. You would only want this operation executing once.
Let's start with the point that you can't distinguish accidental refreshes from purposeful refreshes. So you can only decide to not allow refreshes at all, or in other words require that each form submit must be unique. The best way to do that is to insert a random token into the form.
<?php
$token = /* a randomly generated string */;
$_SESSION['_token'] = $token;
?>
<input type="hidden" name="_token" value="<?php echo $token; ?>" />
After each submit you invalidate the session token. If the token in the session differs from the one submitted with the form, you can discard the POST.
Re comment: You could do this on a per-item basis. For example, here on SO, you may have several question windows open and answer several questions at once. You can make the token on a per-question basis, so the user could have several valid token at any one time, but only one per question.
An example for this scenario would be inserting a row into a registration table. You would only want this operation executing once.
In this case you probably shouldn't be too concerned about the actual POST, but about data consistency as such. You should have some form of unique identification for each user, like his email address. If the address is already registered in the database, you do not register the user again. This is independent of why the user tried to register twice (double submit or actual attempt to register again).
I generally prefer having the POST handler do whatever it needs to do and then redirecting the user to a new page with
header("Location: new-page.php");
so they can refresh without messing anything up
Using tokens in conjunction with the POST/REDIRECT/GET design pattern seems to be the best available solution.
- Setting a single-use token would prevent the user from hitting the back button and trying to submit the form again.
- Redirecting the user and using a view to display the input allows them to hit refresh if they please.
精彩评论