添加一个表单字段并添加一个数学问题来阻止机器人? :(

Adding a form field add with a mathematical question to stop bots? :(

美好的一天,我正在寻求这方面的帮助。在我的 PHP 页面上,我想添加一个简单的数学问题(例如:5+2)来阻止垃圾邮件。请问有什么推荐吗?将不胜感激,如果有什么方法可以改进我的代码,也请随意。

这是我的 PHP 页面和表单字段:

<div class="col-xs-12 col-md-8">
            <?php
            // Contact Form
            function contact_form() {
                if(isset($_POST["name"]) && $_POST["name"] != "")
                {
                    if(!filter_var($_POST["mail"], FILTER_VALIDATE_EMAIL)) {
                        echo "<div class='error'>The email address is not valid</div>";
                        return;
                    }

                    if($_POST["name"] == "" || $_POST["mail"] == "" || $_POST["message"] == "") {
                        echo "<div class='error'>Informations are missing</div>";
                        return;
                    }

                    $name = htmlentities($_POST["name"]);
                    $message = htmlentities($_POST["message"]);
                    $message = wordwrap($message, 70, "\r\n");

                    $to      = '@hotmail.com';
                    $subject = 'Message of '.$name.'';
                    $headers = 'From: ' . "\r\n" .
                        'X-Mailer: PHP/' . phpversion();
                    $message_final = "Someone sent you a message \nNom : ".$name."\nCourriel : ".$_POST["mail"]."\n\n\n".$message;

                    if(mail($to, $subject, $message_final, $headers)) {
                        echo "<div class='success'>Your message was sent. Thank you!</div>";
                        return;
                    } else {
                        echo "<div class='error'>There was an error. You message was not sent</div>";
                        return;
                    }

                }
            }
            contact_form();
            ?>

            <form method="post">
                <div class="form-group">
                    <label for="name">Name</label>
                    <input type="text" class="form-control" id="name" name="name" placeholder="Enter your name" required>
                </div>
                <div class="form-group">
                    <label for="name">Email</label>
                    <input type="email" class="form-control" id="mail" name="mail" placeholder="Enter your email" required>
                </div>
                <div class="form-group">
                    <label for="message">Message</label>
                    <textarea id="message" name="message" class="form-control" rows="3" required></textarea>
                </div>
                <div class="form-group">
                    <button type="submit" class="btn btn-default">Send</button>
                </div>
            </form>
        </div>

干杯

我实际上做了一些你描述的事情。有多种方法可以实现这一点,但一种简单的方法是使用生成随机数学问题、散列答案并将散列插入隐藏字段的函数。用户提交表单,您将提交的答案的哈希值与隐藏字段中的哈希值进行比较。您可能还想考虑对表单使用唯一令牌,这样表单就无法 POST 在没有先获得令牌的情况下进入您的网站。

您可以尝试这样的操作:

function mathQuestion($lo, $hi) {
    $a = mt_rand($lo, $hi);
    $b = mt_rand($lo, $hi);
    $c = $a + $b;
    $hash = md5($c);
    $q = "$a + $b";
    return array($q, $hash);
}
function mathQuestionVerify($c, $hash) {
    return (md5($c) === $hash);
}

然后,在您的表单中,类似于:

$mathQ = mathQuestion(10, 89);
$mathText = $mathQ[0];
$mathHash = $mathQ[1];
echo "<div><label for='mathquestion'>What is $mathText?</label><input id='mathquestion' name='mathquestion'></div>";
echo "<input type='hidden' name='mathanswer' value='$mathHash'>";
echo "<input type='hidden' name='token' value='$token'>";

以上两个字段是数学相关的。 这里的 token 变量是我从中获取的表单中的 CSRF 令牌。 实际上,这只是我之前描述的唯一表单令牌 - 我也在用户登录时使用 CSRF 令牌.

在上面的示例中,当加载表单时,我们添加了两个数字,每个数字都在 10 到 89 之间。您可以将它们更改为任何您想要的。我使用更广泛的数字来完成不太常见的任务,比如密码重置,因为这不是经常做的事情。对于一般的联系表格,您应该将这些数字保持在较小的范围内 - 可能低于 50。

请注意 md5 不是加密安全的sha1 也不是。我实际上也不认为 mt_rand() 是。只是把它扔在那里。我在这种情况下使用 md5,因为我们不处理敏感数据,因此简单、快速的散列函数非常适合我的目的。

我不使用此机制作为我唯一的验证方法,但它肯定可以减缓恶意尝试。如果你想更进一步,你甚至可以使用一个函数将数字问题重写成文本,使机器人更难发送垃圾邮件。

根据您的具体情况,您可以尝试这样的操作:

<div class="col-xs-12 col-md-8">
        <?php
        // Contact Form
        function contact_form() {
            if(isset($_POST["name"]) && $_POST["name"] != "")
            {
                if(!isSet($_POST['mathanswer'] || !mathQuestionVerify($_POST['mathanswer'], $_POST['mathhash'])) {
                    echo "<div class='error'>Incorrect answer.</div>";
                    return;
                }
                if(!filter_var($_POST["mail"], FILTER_VALIDATE_EMAIL)) {
                    echo "<div class='error'>The email address is not valid</div>";
                    return;
                }

                if($_POST["name"] == "" || $_POST["mail"] == "" || $_POST["message"] == "") {
                    echo "<div class='error'>Informations are missing</div>";
                    return;
                }

                $name = htmlentities($_POST["name"]);
                $message = htmlentities($_POST["message"]);
                $message = wordwrap($message, 70, "\r\n");

                $to      = '@hotmail.com';
                $subject = 'Message of '.$name.'';
                $headers = 'From: ' . "\r\n" .
                    'X-Mailer: PHP/' . phpversion();
                $message_final = "Someone sent you a message \nNom : ".$name."\nCourriel : ".$_POST["mail"]."\n\n\n".$message;

                if(mail($to, $subject, $message_final, $headers)) {
                    echo "<div class='success'>Your message was sent. Thank you!</div>";
                    return;
                } else {
                    echo "<div class='error'>There was an error. You message was not sent</div>";
                    return;
                }

            }
        }
        contact_form();
        ?>

        <form method="post">
            <div class="form-group">
                <label for="name">Name</label>
                <input type="text" class="form-control" id="name" name="name" placeholder="Enter your name" required>
            </div>
            <div class="form-group">
                <label for="name">Email</label>
                <input type="email" class="form-control" id="mail" name="mail" placeholder="Enter your email" required>
            </div>
            <div class="form-group">
                <label for="message">Message</label>
                <textarea id="message" name="message" class="form-control" rows="3" required></textarea>
            </div>
            <div class="form-group">
                <button type="submit" class="btn btn-default">Send</button>
            </div>
<?php
$mathQ = mathQuestion(5, 15); # ask user to add 2 random numbers between 5 & 15
$mathText = $mathQ[0];
$mathHash = $mathQ[1];
echo "<div><label for='mathquestion'>What is $mathText?</label><input id='mathquestion' name='mathquestion'></div>";
echo "<input type='hidden' name='mathanswer' value='$mathHash'>";
?>

        </form>
    </div>