在PHP中提交表单时如何防止多个插入?
有时用户可能会按两次Enter
,并且插入两次。
有没有一个解决scheme来防止这个,而不是检查是否已经有一个相同的title
和content
的职位?
有几个解决这个问题的方法:
-
发布时使用Javascript来禁用表单的提交button。 这是绝对不是一个万无一失的方法。 提交表单实际上没有点击button是非常容易的,而且对禁用JavaScript的用户也不适用。 我绝对不会推荐这种方法。
例:
<script language="javascript"> <!-- function disableSubmitButton() { // you may fill in the blanks :) } --> </script> <form action="foo.php" method="post"> <input type="text" name="bar" /> <input type="submit" value="Save" onclick="disableSubmitButton();"> </form>
-
使用PHP会话将post会话variables(例如$ _SESSION ['posttimer'])设置为当前时间戳。 在PHP中实际处理表单之前,检查$ _SESSION ['posttimer']variables是否存在,并检查某个时间戳差异(IE:2秒)。 这样,你可以很容易地过滤掉双重提交。
例:
// form.html <form action="foo.php" method="post"> <input type="text" name="bar" /> <input type="submit" value="Save"> </form> // foo.php if (isset($_POST) && !empty($_POST)) { if (isset($_SESSION['posttimer'])) { if ( (time() - $_SESSION['posttimer']) <= 2) { // less then 2 seconds since last post } else { // more than 2 seconds since last post } } $_SESSION['posttimer'] = time(); }
-
在每个POST中包含一个唯一的标记。 在这种情况下,您还可以将会话variables设置为要包含的令牌,然后在窗体中呈现该令牌。 表单提交后,您将重新生成令牌。 当提交的标记与会话中的标记不匹配时,表单已被重新提交并应被宣布为无效。
例:
// form.php <?php // obviously this can be anything you want, as long as it is unique $_SESSION['token'] = md5(session_id() . time()); ?> <form action="foo.php" method="post"> <input type="hidden" name="token" value="<?php echo $_SESSION['token'] ?>" /> <input type="text" name="bar" /> <input type="submit" value="Save" /> </form> // foo.php if (isset($_SESSION['token'])) { if (isset($_POST['token'])) { if ($_POST['token'] != $_SESSION['token']) { // double submit } } }
在post中使用唯一标记,以便每个post/回发只处理一次。
禁用提交button不是一个很好的解决scheme,因为人们可以closuresJavaScript,或做其他奇怪的事情。 客户端validation是一个好的开始,但也应该始终使用服务器端处理来进行备份。
生成一个唯一的一次性使用密钥,用表单提交。
依靠Javascript是一个坏主意,因为它可能已被用户禁用在客户端。 使用密钥scheme,当服务器接收到提交时,可以locking该密钥的提交。 无论你喜欢,你都可以对重复的提交做出回应。
对于这种方法的工作,键必须是独特的,非常难以预测。 否则,某些表单可能会因关键冲突而被locking。 所以你不必跟踪每个表单提交的密钥,避免冲突,密钥应该过期与该用户的会话。 另外要注意的是,如果恶意用户能够预测密钥,那么您的代码可能容易受到某种劫持或DOS攻击。
防止重复的表单提交显示了一个没有JavaScript的做法。
提交表单( onsubmit
)后,使用Javascript禁用提交button。
请注意,如果用户禁用Javascript,他们仍然可以提交两次。 无论这种情况是否经常发生,足以certificate你的代码(如你在你的问题中提到的那样)是由你自己决定的。
或者,使用一次性表单键。
我使用这个:
$form_token = $_SESSION['form_token'] = md5(uniqid());
发送$ form_token的forms,然后…
我检查了form_token:
if($_SESSION['form_token'] != $_POST['form_token']) { echo 'Error'; }
一旦用户提交表单,使用JavaScript禁用提交button。 这就是,例如,当你回答一个问题时,StackOverflow使用。
例如
<input type="submit" onclick="this.disabled=true" />
按两次提交很less会导致多个插入,但如果你想要一个简单的溶剂,使用
onsubmit="document.getElementById('submit').disabled = true"
在表单标签中,只要你提交你的提交buttonid="submit"
一旦点击button,就可以使用JavaScript来禁用button。
onclick="this.disabled=true;forms[0].submit();"
另一种创build确认页面的方法,用户可以最终按下提交button。 这可能会减less这种可能性。
Aron Rotteveel's 在每个POST上都包含一个独特的令牌 。 但是,我的表单仍然会在用户刷新页面时提交(F5)。 我设法通过添加重置来解决这个问题:
// reset session token $_SESSION['token'] = md5( $_POST['token'] . time() );
我的最终脚本是这样的:
if (isset($_SESSION['token'])) { if (isset($_POST['token'])) { if ($_POST['token'] != $_SESSION['token']) { echo '<h3>Oops! You already submitted this request.</h3>'; } else { // process form // reset session token $_SESSION['token'] = md5( $_POST['token'] . time() ); } } else { echo 'post token not set'; $_SESSION['token'] = md5( $somevariable . time() ); } }
哦! 不要忘记添加session_start();
在<!DOCTYPE>
之前
我是一个PHP新手,所以请纠正我,如果你发现违规行为。
使用JavaScript来阻止它发送