使用会话存储PHP联系表单的反垃圾邮件查询的答案

时间:2013-12-19 23:21:00

标签: php forms session

我需要帮助我的网站的联系表格。我将首先解释我的表单是如何设置的。我的网站有一个页面(index.php),有三个部分。最后一个是“联系我们”,它有一个表格,用户应该输入他们的姓名,电子邮件地址和信息。

我的联系表单工作正常,但它需要一些安全措施来防范垃圾邮件机器人。所以我决定添加一个简单的反垃圾邮件问题,例如“2 + 2”。我希望这个问题每次都不同,这就是给我带来问题的原因。如果你能指出我正确的方向来解决这个问题,我真的很感激!

这是我正在使用的代码。我将在下面解释。

<a name="contact"><h2>Contact Us</h2></a>
<?php
$operation = mt_rand(0, 2);
switch ($operation) {
    case 0:
        $r1    = mt_rand(0, 50);
        $r2    = mt_rand(0, 50);
        $r3    = $r1 + $r2;
        $query = "How much is $r1 + $r2?";
        break;
    case 1:
        $r1 = mt_rand(0, 50);
        do {
            $r2 = mt_rand(0, 50);
        } while ($r2 >= $r1);
        $r3        = $r1 - $r2;
        $query = "How much is $r1 - $r2?";
        break;
    case 2:
        $r1    = mt_rand(0, 10);
        $r2    = mt_rand(0, 10);
        $r3    = $r1 * $r2;
        $query = "How much is $r1 × $r2?";
        break;
}
if (isset($_POST["name"]) && isset($_POST["email"]) && isset($_POST["human"]) && isset($_POST["message"])) {
    $name    = spam_check('name');
    $from    = spam_check('email');
    $subject = empty($_POST['subject']) ? "Contact Form Message" : spam_check('subject');
    $human   = spam_check('human');
    $message = "<!DOCTYPE HTML><html><body><p>";
    $message .= "<strong>Name:</strong> " . $name . "<br>";
    $message .= "<strong>Email:</strong> <a href=\"mailto:" . $from . "\">" . $from . "</a></p>";
    $message .= "<p><strong>Message:</strong><br>" . spam_check('message') . "</p>";
    $message .= "</body></html>";
    $to      = "hello@example.com";
    $headers = "From: Me<hello@example.com>\nReply-To:" . $name . "<" . $from . ">\n";
    $headers .= "Mime-Version: 1.0\n";
    $headers .= "Content-Type: text/html; charset=UTF-8";
    if ($_POST['submit']) {
        if (!strcmp($human, $_SESSION['human'])) {
            if (mail($to, $subject, $message, $headers)) {
                echo "<p class=\"success\">Thanks for contacting us.</p>";
            } else {
                echo "<p class=\"failure\">Something went wrong, please try again!</p>";
            }
            unset($_SESSION['query']);
            unset($_SESSION['human']);
        } else {
            echo "<p class=\"warning\">You did not answer our anti-spam question. Do you need <a href=\"http://www.google.com/search?q=" . urlencode($_SESSION['query']) . "&amp;hl=en\">help</a>?</p>";
        }
    } else {
        echo "<p class=\"failure\">Something went wrong, please try again!</p>";
    }
}
if (!isset($_SESSION['human'])) {
    $_SESSION['query'] = $query;
    $_SESSION['human'] = "$r3";
} ?>
<form action="#contact" method="post">
    <input type="text" name="name" placeholder="Name" title="Name" required>
    <input type="email" name="email" placeholder="Email" title="Email" required>
    <input type="text" name="subject" placeholder="Subject" title="Subject">
    <input type="text" name="human" placeholder="<?php echo $query; ?>" title="<?php echo $query; ?>" required>
    <textarea name="message" placeholder="Write your message here&hellip;" title="Message" rows="10" cols="40" required></textarea>
    <input type="submit" name="submit" value="Send">
</form>

以下是我用上述代码尝试实现的解释:首先,我生成一个随机数,以确定问题是加法,减法还是乘法。如果我得到:

  • 0 ,我生成两个低于50的随机数并添加它们。
  • 1 ,我生成两个低于50的随机数并减去它们(注意:第二个数字不得大于第一个数字,以防止出现负面结果)。
  • 2 ,我生成两个低于10的随机数并将它们相乘。

问题的结果存储在$r3中,问题本身存储在$query中。

接下来,我检查用户是否已提交表单。如果有,我使用名为spam_check的函数提取输入。 spam_check应该停止标头注入。它似乎工作,虽然我没有彻底测试它。一旦我提取了每个字段的值,我就开始构建电子邮件的正文和标题。这也有效。坚持下去,我们即将解决问题。

下一步是检查用户对反垃圾邮件问题($human)的回答是否与$r3的值匹配。这是我无法工作的部分。我曾经有一个简单的检查:$human == $r3,但我很快意识到它无法正常工作,因为一旦您提交表单,页面就会重新加载并且$r3成为新的数字。所以我决定可能会议是出去的方式。

在最后一行中,$r3的值存储在$_SESSION['human']中,如果$_SESSION['human']未设置(例如,第一次加载页面)。要确定用户是否正确回答,我使用了!strcmp($human, $_SESSION['human']),但它不起作用,因为$_SESSION['human']没有存储值!

看起来,一旦您提交表单,会话就会以某种方式丢失并重置存储的值。如何存储和保存$r3的值?

我已经检查过我的服务器中是否启用了会话,而且我还找到了临时会话文件(例如query|s:20:"How much is 19 - 12?";human|s:1:"7";),所以我没有其他地方寻找解决方案。

1 个答案:

答案 0 :(得分:0)

您可能需要运行

session_start();

在代码的开头。有关详细信息,请参阅http://www.php.net/session_start。请注意,您应该将session_start()放在浏览器的任何其他输出之前。