You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP随机数生成器与$_POST对比验证失效问题排查

解决PHP表单反垃圾随机数验证失效的问题

咱先搞明白为啥会出这问题哈——你的随机数生成逻辑在页面加载和表单提交时会重新生成新值,导致验证时对比的根本不是用户看到的那组数字之和!

举个例子:用户打开页面时,生成的是3+5=8,用户输入8提交;这时候页面重新执行PHP代码,又生成了2+4=6,然后拿6去对比用户输入的8,那肯定提示错误啊!

给你俩靠谱的解决方案,按需选就行:

方案一:用Session存储正确答案(更安全)

这种方法会把用户看到的那组数字的和存在服务器端的Session里,提交时用这个存储的值验证,不会被用户篡改。

步骤:

  1. 在所有PHP代码最顶部开启Session(必须放在任何输出之前)
  2. 生成随机数时,把数字和正确的和存入Session,避免刷新页面就变题
  3. 验证时用Session里的正确和对比用户输入的值

代码修改:

首先加Session初始化:

session_start(); // 一定要放在PHP代码最开头,不能有任何HTML输出之前

然后修改随机数生成逻辑:

// 只有当Session里没存题的时候才生成新题
if (!isset($_SESSION['correct_sum'])) {
    $num1 = mt_rand(1, 9);
    $num2 = mt_rand(1, 9);
    $_SESSION['num1'] = $num1;
    $_SESSION['num2'] = $num2;
    $_SESSION['correct_sum'] = $num1 + $num2;
    $str1 = (string) $num1;
    $str2 = (string) $num2;
} else {
    // 如果已经有存的题,就用之前的数字显示
    $num1 = $_SESSION['num1'];
    $num2 = $_SESSION['num2'];
    $str1 = (string) $num1;
    $str2 = (string) $num2;
}

最后修改验证逻辑:

if (isset($_POST["submit"])) {
    $name = $_POST['name'];
    $email = $_POST['email'];
    $message = $_POST['message'];
    $human = intval($_POST['human']);
    $from = 'STEM and Buds Contact Form';
    $to = 'saifanchey@gmail.com';
    $subject = $_POST['subject'];
    $reason = $_POST['reason'];

    // 用Session里的正确和验证
    if ($human !== $_SESSION['correct_sum']) {
        $errHuman = 'Your anti-spam is incorrect';
    }

    // 验证完可以销毁Session里的值,避免用户刷新后重复用同一道题
    unset($_SESSION['correct_sum'], $_SESSION['num1'], $_SESSION['num2']);
}

方案二:用隐藏表单字段存储正确答案(更简单)

这种方法直接把正确的和放在表单的隐藏字段里,提交时一起传回来验证,优点是不用折腾Session,缺点是懂点前端的用户能通过查看源码看到答案,但对付普通垃圾机器人足够了。

代码修改:

在HTML的验证输入框旁边加一个隐藏字段:

<div class="form-group">
    <label for="human" class="col-sm-2 control-label"><?php echo $str1 . " + " . $str2 . " = ?"; ?></label>
    <div class="col-sm-10">
        <input type="text" class="form-control" id="human" name="human" placeholder="Your Answer">
        <!-- 添加这个隐藏字段存正确的和 -->
        <input type="hidden" name="correct_sum" value="<?php echo $sum; ?>">
        <?php echo "<p class='text-danger'>$errHuman</p>"; ?>
    </div>
</div>

然后修改验证逻辑:

if (isset($_POST["submit"])) {
    $name = $_POST['name'];
    $email = $_POST['email'];
    $message = $_POST['message'];
    $human = intval($_POST['human']);
    // 获取隐藏字段里的正确和
    $correct_sum = intval($_POST['correct_sum']);
    $from = 'STEM and Buds Contact Form';
    $to = 'saifanchey@gmail.com';
    $subject = $_POST['subject'];
    $reason = $_POST['reason'];

    // 用隐藏字段的值验证
    if ($human !== $correct_sum) {
        $errHuman = 'Your anti-spam is incorrect';
    }
}

选哪个方案看你的需求,追求安全选Session,图省事选隐藏字段,两种都能解决你现在的问题~

内容的提问来源于stack exchange,提问作者Saif Ali

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 06:34:02