2

我正在使用以下代码进行测试:

<?php
$db = new PDO('mysql:host=localhost;dbname=test', 'root', 'root');

if(filter_has_var(INPUT_POST, 'submit')) {

  $r = $db->query('SELECT * FROM test WHERE value="'.$_POST['value'].'"');
  $n = $r->rowCount();

  for ($i=0; $i<=10000000; $i++) {
    // do nothing
  }

  if  (!$n) {
    $db->query('INSERT INTO test (id, value) VALUES (NULL, "'.$_POST['value'].'")');
  }

}
?>

<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
  <input type="text" name="value" value="">
  <input type="submit" name="submit" value="Submit">
</form>

在 safari 中测试上述表单时,我可以通过快速单击提交按钮多次将相同的值提交到我的数据库中。

但是,当我使用此代码进行测试时:

<?php
$db = new PDO('mysql:host=localhost;dbname=test', 'root', 'root');

if(filter_has_var(INPUT_POST, 'submit')) {

  for ($i=0; $i<=10000000; $i++) {
    // do nothing
  }

  $r = $db->query('SELECT * FROM test WHERE value="'.$_POST['value'].'"');
  $n = $r->rowCount();

  if  (!$n) {
    $db->query('INSERT INTO test (id, value) VALUES (NULL, "'.$_POST['value'].'")');
  }

}
?>

条件有效,无论我单击提交按钮的速度有多快,我都无法多次提交相同的值。

是否有可靠的方法来防止第一个代码片段发生重复的数据库插入,使其行为与第二个片段一样?

4

1 回答 1

2

一般来说,客户端onsubmit处理程序可以帮助阻止意外的快速提交,但我通常选择使用_SESSION变量的服务器端解决方案。只需创建一个$_POST数组的哈希,将其存储为会话变量,然后将下一个提交_POST的哈希版本进行比较:

session_start();
//if this is the first time they've posted, just create a placeholder session var
if (!isset($_SESSION['repost_hash'])){$_SESSION['repost_hash']="";}

//if the post array is a duplicate, nullify the submission
if (isset($_POST) && md5(serialize($_POST)) == $_SESSION['repost_hash']){ 
   unset($_POST);
} else { //otherwise, if this is new data, update the stored hash
   $_SESSION['repost_hash'] = md5(serialize($_POST));
}
...

如果您只想在短时间内停止重复提交,您还可以让第二个$_SESSION变量存储最后一次哈希的时间,这样您就可以在一两秒后将其过期。

于 2012-12-05T03:12:22.460 回答