php选择框的session防止重复提交问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了php选择框的session防止重复提交问题相关的知识,希望对你有一定的参考价值。

//数据接口连接正常,就是session方式不能实现判断是否重复提交<meta charset="utf-8"><?php $App = new AppInfo(); $appData=$App->appInfo; //引入数据接口 if (!isset($_POST['originator'])) if(!session_id())session_start(); $code=mt_rand(0,1000000); $_SESSION['code']=$code; //生成随机数?><html> <title>用户提交应用界面</title> <form id="form2" name="form2" method="post" action=""> <div align="left"> 请选择数据: <select name="select" id="select" type="hidden"> <?php
///循环接口数据到下拉框 foreach ($appData as $k=>$v) ?> <option value="<?php echo $v['id'] ?>"><?php echo $v['name'];?> </option> <?php ?> </select>
//隐藏值进行传递 <input type="hidden" name="originator" value="<?=$value?>"> <input type ="submit" value ="提交"/> </div> </form> <input type="button" value="返回主页" onclick="location.href='/player/server/views/index.html'"><?php
//判断是否重复提交 if(isset($_POST['select']))////var_dump($_POST['originator']);/////var_dump($_SESSION['code']); if($_POST['originator']==$_SESSION['code']) $select=$_POST['select']; $uss = new UserAction(); $uss->userSubmit($select);//提交数据// $code=mt_rand(0,1000000); $_SESSION['code']=$code;//这里赋值 else echo '请不要刷新页面或重复提交表单!'; ?></html>/////session方式选择表单提交判断是否重复提交

参考技术A 大致看了下,主要两个问题:
1)session_start(),代码里仅在没有提交且没有生成过session时才执行,这直接导致提交时$_SESSION未定义
2)隐藏值originator,value="<?=$value?>">,$value从哪来的?应该是$code吧。但如果是$code,那必然又和$_SESSION['code']一致了

可以考虑以$_SESSION['code']是否存作为判断是否第一次提交的依据,示例代码如下:
----------------------------------------------------------
<?php session_start(); ?>

<!-- 页面显示部分 -->
<html>
<form id="form2" name="form2" method="post" action="">
<div align="left">请选择数据:
<select name="select" id="select">
<?php
$App = new AppInfo();
$appData=$App->appInfo;
foreach ($appData as $k=>$v)
echo '<option value="', $v['id'], '">', $v['name'], '</option>';

?>
</select>
<input type ="submit" value ="提交"/>
</div>
</form>
<input type="button" value="返回主页" onclick="location.href='/player/server/views/index.html'">

<!-- 提交处理部分 -->
<?php
if( isset( $_POST['select'] ) )
if( isset( $_SESSION['code'] ) )
echo '请不要刷新页面或重复提交表单!';
else
$uss = new UserAction();
$uss->userSubmit($_POST['select']);
$_SESSION['code'] = TRUE;

?>
</html>追问

亲,很感谢你耐心的看完了我的代码,还整理了出来。本意是在本页完成提交数据,又在本页完成判断是否重复提交,现在的情况类似于a-》b,b-》c,没法判断a和c的关系,存在逻辑错误。。你给的$_SESSION= mt_rand(0,1000000000),少了这个隐藏值,故没法判断是否是重复。

追答

上面的示例中,没有采用隐藏值的方式,直接以 $_SESSION['code']是否存在作为判断依据的

用其他内容替换了你的AppInfo和UserAction,测试过的,应该可以达到你想要的效果

另外,上面的示例只是一个页面脚本,为了看着方便,加了各部分功能的标注。你可以把你的AppInfo和UserAction加到最前面,运行试试看

追问

很感谢,你的代码很规范,很明了,这一点我采用了,试过了你给的方法,可能是太简洁了,没法实现//第二次提交的时候,这个时候的意思判断为已经存在了。这里第二次表示第二次点提交,而不是第二次同样的数据提交//if( isset( $_SESSION['code'] ) )echo '请不要刷新页面或重复提交表单!';else。。。

追答

在同一页面中反复提交,是可以判断是否重复的
如果是新开一个浏览器窗口出来,因为是一个新会话,会产生新的session,新开窗口的第一次提交肯定不会被认为是重复提交

你是说在同一页面上,两次提交相同值可以判断重复提交,而提交不同值判断不出来?这不太可能啊,是否重复提交的判断依据是 $_SESSION['code']是否存在,与$_POST['select']的值完全无关

追问

朋友,事实是这样的,如果按你给的方案,昨天晚上就已经实现出来了,可是发现只能实现一条,就是默认的那条,一直在改都没改出来。逻辑上就是a传b,b传c,怎样才能判断c=a,这样而已;你给的方案里$_session['code']值恒为ture值

追答

我已经被绕晕了,私信

本回答被提问者采纳
参考技术B 加个隐藏域 <input type="hidden" name="toket" value="dasdaiweuhfja">
值 放到 session里一份 提交后 判断是否相等 是就确认并清空session中的值追问

上面加了隐藏域的://隐藏值进行传递 "> //就是这样传的,可是没用。这百度也真是的,给我提问的东西全都打乱了,

追答

你的$value因该改成$code的吧 你的$value值是什么?

追问

上面的随机数

追答

那也是$code啊。
$value 你有给他赋值?

追问

嗯,其实是一个值,我写错了而已,$_SESSION['code']=$code=mt_rand($min,$max);

追答

呵呵

参考技术C 朋友你这个逻辑有问题,永远都是相等的,自然测不出来追问

那给个方案呗,这有点头疼了,主要是隐藏值获取不到,,

如何使用 PHP 会话来防止重复提交表单?

【中文标题】如何使用 PHP 会话来防止重复提交表单?【英文标题】:How do I use a PHP session to prevent duplicate form submissions? 【发布时间】:2017-06-03 11:39:48 【问题描述】:

我想停止向我的网页提交重复的表单。我到处寻求帮助,我看到使用 $_SESSION 变量;但我看不到会话和表单如何在多个用户帐户的上下文之外相互连接。

谁能告诉我这个过程是如何工作的?

编辑:我不想停止多次提交表单;只是为了防止重新提交具有相同值的表单(例如在页面刷新时)。

处理完表单后,用户应该会看到成功/错误消息,然后再次看到表单。

【问题讨论】:

出于其他原因(XSRF)需要使用会话令牌,它间接解决了双重提交。虽然万无一失且更安全,但在某些情况下,Post-Redirect-Get pattern 可以实现更用户友好的方式。两者都应该使用,但后者可以防止多次点击(虽然不确定旧浏览器)和浏览器的后退按钮重新提交 - 所以它涵盖了 99% 的情况(您只能通过停止正在进行的请求或使用错误的 ajax 请求实现)。 @shudder 所以如果我使用会话令牌检查重复提交,如果发生重新提交是否有问题? 取决于你所说的问题。您肯定会阻止重新提交,并且无论如何您都需要处理这些情况,但在广泛的背景下,它们会更频繁地出现,并且通常没有用户的故意行为。您的回复应该是什么并不明显 - “无效令牌”(准确,但当诚实的用户不知道刚刚发生的事情时,您可能不关心那些滥用应用程序的人),“表格已经发送”(我点击了两次还是什么?),“编辑类型的表单页面”(有时),“空表单页面”(我想添加另一个)?很难保持一致。 ^ 我的意思是防止多次点击有什么好处? 使用会话与 PRG 防止多次点击的优势之一是:每次都有效。您需要两者,它们是互补的,例如输入验证和异常处理。 【参考方案1】:

基本上您需要使用唯一的 SESSION 值两次。一旦您尝试提交表单中的某个位置并存储在 $_SESSION 变量中。当表单被 POST 并且两个值都匹配时,我们提交成功,当表单被 POST 但值不同时,不会发生提交。

即:

PHP 页面顶部的某处:

    <?php
        session_start(); // first line of your PHP page
        $_SESSION['secretFormValue'] = isset($_SESSION["secretFormValue"]) ? $_SESSION["secretFormValue"] : md5(microtime()); // generate some unique session value

       // assign submitted **secretFormValue** from your form to a local variable
        $secretFormValue = isset($_POST["secretFormValue"])? filter_var($_POST["secretFormValue"], FILTER_SANITIZE_STRING) : '';

       // check if the value is present in the **secretFormValue** variable
        if($secretFormValue != '') 

           // check if both values are the same
           if($_SESSION["secretFormValue"] == $secretFormValue) 

                // Process form values & submission ...
                // add your own code...

                unset($_SESSION["secretFormValue"]);

            else 

               echo "Duplicate submission";
           

         else 

           // do some other thing
        

表单下方某处:

<input type="hidden" name="secretFormValue" value"<?php echo $_SESSION['secretFormValue']; ?>">

***我没有对此进行测试,所以请在有错误的情况下发表评论,谢谢。*

编辑: 如果您需要阻止在页面刷新时提交,您可以包括在成功提交时清除所有 POST 值,以便刷新会因为 POST 为空而失败,即:

unset($_POST); // place it right before unset($_SESSION["secretFormValue"]);

在提交后包含重定向到不同页面(即感谢页面),即:

header("Location:ThankYouPage.php"); // place it right after unset($_SESSION["secretFormValue"]);

或者只是在其他 SO 帖子中找到了这个:

https://en.wikipedia.org/wiki/Post/Redirect/Get

【讨论】:

我还没有尝试过(网站其他地方的问题);但是在用户点击“提交”并重新加载页面后,会话变量是否会更改(第 3 行)并使它们永远不会匹配? 是的,这个想法是......“停止向我的网页提交重复的表单......”正如你最初要求的那样。这意味着同一个表格永远不能提交两次。我有一种感觉,您还需要在第一次提交完成后停止显示表单(改为显示感谢消息等)。我认为您可能需要澄清您试图阻止的具体情况。您是否尝试将表单提交限制为每位访问者 1 个? 刚刚编辑了我的问题。让我知道我是否应该提供任何其他信息。 所以两个“secretFormValues”在第一次提交时是不同的;因此它作为副本返回。将 $_SESSION['secretFormValue'] = md5(microtime()); 移动到代码的末尾使其看起来正常工作。 是的,有不止一种方法可以解决这个问题,您可能还想考虑一个场景,有人使用自动脚本针对您的表单页面发布 1000 次提交,因此 SESSION 位于顶部...谢谢。【参考方案2】:

一旦该访问者提交了表单,您就可以简单地设置一个$_SESSION['submittedForm'] = true; 变量。然后,您可以在他们下次访问表单页面时检查该会话数据,并且要么不显示表单,要么在他们尝试再次提交时抛出错误消息。

【讨论】:

【参考方案3】:

我建议另一种方法。您要解决的问题有两种变体:

    当用户在提交后刷新页面时,如何防止/检测表单被多次提交(通常是意外)? 如何防止表单数据不是来自我页面上显示的实际表单的提交(或至少使其更难提交)?

Milan 的解决方案解决了这两个问题,但它本身就产生了一个问题:如果用户在多个选项卡/窗口中打开了相同的页面(请记住,它们共享同一个会话),这将中断。

如果您不关心问题 #2,则通过在会话数据中保留已提交的表单 ID 列表来执行“被动”方法会更容易:

$formID = (isset($_POST["__form_id"]) ? $_POST["__form_id"] : false);
$submittedforms = (isset($_SESSION["submittedforms"]) ? $_SESSION["submittedforms"] : array());

// Check whether this form ID has been submitted before
if (in_array($formID, $submittedforms)) 
    printf("Duplicate submission.");
    exit;


// Store the ID of this form submission
$submittedforms[] = $formID;
$_SESSION["submittedforms"] = $submittedforms;

// Continue form processing...

如果您还需要防止未经授权的(自动)表单提交,则需要一种积极的方法。我会扩展 Milan 的解决方案,然后将 多个 表单 ID 存储在您的会话数据中(在一个数组中),每个生成的表单一个;然后在提交时一一删除。

【讨论】:

以上是关于php选择框的session防止重复提交问题的主要内容,如果未能解决你的问题,请参考以下文章

php防止表单重复提交

PHP+SESSION防止表单重复提交

php通过记录IP来防止表单重复提交方法分析

PHP简单利用token防止表单重复提交

php防止post重复提交

PHP 防止表单重复提交